From a82f72eb04d4b5766f12d94febdf2f989ca7210a Mon Sep 17 00:00:00 2001 From: "Matthias P. Braendli" Date: Thu, 17 Aug 2017 15:25:47 +0200 Subject: Add number of threads setting for MemlessPoly --- dpd/dpd.ini | 4 ++++ src/ConfigParser.cpp | 3 +++ src/ConfigParser.h | 2 +- src/DabMod.cpp | 6 ++++-- src/DabModulator.cpp | 7 +++++-- src/DabModulator.h | 5 ++++- src/MemlessPoly.cpp | 29 ++++++++++++++++++----------- src/MemlessPoly.h | 3 ++- 8 files changed, 41 insertions(+), 18 deletions(-) diff --git a/dpd/dpd.ini b/dpd/dpd.ini index 08564d9..21d7d45 100644 --- a/dpd/dpd.ini +++ b/dpd/dpd.ini @@ -24,6 +24,10 @@ enabled=1 enabled=1 polycoeffile=dpdpoly.coef +# How many threads to use for the predistorter. +# If not set, detect automatically. +#num_threads=2 + [output] # to prepare a file for the dpd/iq_file_server.py script, # use output=file diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index 459811f..f27eb08 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -172,6 +172,9 @@ static void parse_configfile( if (pt.get("poly.enabled", 0) == 1) { mod_settings.polyCoefFilename = pt.get("poly.polycoeffile", "default"); + + mod_settings.polyNumThreads = + pt.get("poly.num_threads", 0); } // Output options diff --git a/src/ConfigParser.h b/src/ConfigParser.h index 22a4fc5..89f0fb7 100644 --- a/src/ConfigParser.h +++ b/src/ConfigParser.h @@ -75,7 +75,7 @@ struct mod_settings_t { std::string filterTapsFilename = ""; std::string polyCoefFilename = ""; - + unsigned polyNumThreads = 0; #if defined(HAVE_OUTPUT_UHD) OutputUHDConfig outputuhd_conf; diff --git a/src/DabMod.cpp b/src/DabMod.cpp index 7c342a2..1f10fb8 100644 --- a/src/DabMod.cpp +++ b/src/DabMod.cpp @@ -328,7 +328,8 @@ int launch_modulator(int argc, char* argv[]) mod_settings.normalise, mod_settings.gainmodeVariance, mod_settings.filterTapsFilename, - mod_settings.polyCoefFilename); + mod_settings.polyCoefFilename, + mod_settings.polyNumThreads); if (format_converter) { flowgraph.connect(modulator, format_converter); @@ -433,7 +434,8 @@ int launch_modulator(int argc, char* argv[]) mod_settings.normalise, mod_settings.gainmodeVariance, mod_settings.filterTapsFilename, - mod_settings.polyCoefFilename); + mod_settings.polyCoefFilename, + mod_settings.polyNumThreads); if (format_converter) { flowgraph.connect(modulator, format_converter); diff --git a/src/DabModulator.cpp b/src/DabModulator.cpp index 5282a2d..ccc2085 100644 --- a/src/DabModulator.cpp +++ b/src/DabModulator.cpp @@ -63,7 +63,8 @@ DabModulator::DabModulator( float& digGain, float normalise, float gainmodeVariance, const std::string& filterTapsFilename, - const std::string& polyCoefFilename + const std::string& polyCoefFilename, + unsigned int polyNumThreads ) : ModInput(), myOutputRate(outputRate), @@ -77,6 +78,7 @@ DabModulator::DabModulator( myFlowgraph(NULL), myFilterTapsFilename(filterTapsFilename), myPolyCoefFilename(polyCoefFilename), + myPolyNumThreads(polyNumThreads), myTiiConfig(tiiConfig) { PDEBUG("DabModulator::DabModulator(%u, %u, %u, %zu) @ %p\n", @@ -222,7 +224,8 @@ int DabModulator::process(Buffer* dataOut) shared_ptr cifPoly; if (not myPolyCoefFilename.empty()) { - cifPoly = make_shared(myPolyCoefFilename); + cifPoly = make_shared( + myPolyCoefFilename, myPolyNumThreads); rcs.enrol(cifPoly.get()); } diff --git a/src/DabModulator.h b/src/DabModulator.h index 0c691dd..56a6f91 100644 --- a/src/DabModulator.h +++ b/src/DabModulator.h @@ -56,7 +56,9 @@ public: float& digGain, float normalise, float gainmodeVariance, const std::string& filterTapsFilename, - const std::string& polyCoefFilename); + const std::string& polyCoefFilename, + unsigned int polyNumThreads); + DabModulator(const DabModulator& other) = delete; DabModulator& operator=(const DabModulator& other) = delete; virtual ~DabModulator(); @@ -82,6 +84,7 @@ protected: OutputMemory* myOutput; std::string myFilterTapsFilename; std::string myPolyCoefFilename; + unsigned int myPolyNumThreads; tii_config_t& myTiiConfig; size_t myNbSymbols; diff --git a/src/MemlessPoly.cpp b/src/MemlessPoly.cpp index 71ceac3..b0d950c 100644 --- a/src/MemlessPoly.cpp +++ b/src/MemlessPoly.cpp @@ -53,9 +53,10 @@ static const std::array default_coefficients({{ }}); -MemlessPoly::MemlessPoly(const std::string& coefs_file) : +MemlessPoly::MemlessPoly(const std::string& coefs_file, unsigned int num_threads) : PipelinedModCodec(), RemoteControllable("memlesspoly"), + m_num_threads(num_threads), m_coefs(), m_coefs_file(coefs_file), m_coefs_mutex() @@ -63,6 +64,16 @@ MemlessPoly::MemlessPoly(const std::string& coefs_file) : PDEBUG("MemlessPoly::MemlessPoly(%s) @ %p\n", coefs_file.c_str(), this); + if (m_num_threads == 0) { + const unsigned int hw_concurrency = std::thread::hardware_concurrency(); + etiLog.level(info) << "Polynomial Predistorter will use " << + hw_concurrency << " threads (auto detected)"; + } + else { + etiLog.level(info) << "Polynomial Predistorter will use " << + m_num_threads << " threads (set in config file)"; + } + RC_ADD_PARAMETER(ncoefs, "(Read-only) number of coefficients."); RC_ADD_PARAMETER(coeffile, "Filename containing coefficients. When written to, the new file gets automatically loaded."); @@ -156,12 +167,15 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut) std::lock_guard lock(m_coefs_mutex); const unsigned int hw_concurrency = std::thread::hardware_concurrency(); - if (hw_concurrency) { - const size_t step = sizeOut / hw_concurrency; + const unsigned int num_threads = + (m_num_threads > 0) ? m_num_threads : hw_concurrency; + + if (num_threads) { + const size_t step = sizeOut / num_threads; vector > flags; size_t start = 0; - for (size_t i = 0; i < hw_concurrency - 1; i++) { + for (size_t i = 0; i < num_threads - 1; i++) { flags.push_back(async(launch::async, apply_coeff, m_coefs, in, start, start + step, out)); @@ -177,13 +191,6 @@ int MemlessPoly::internal_process(Buffer* const dataIn, Buffer* dataOut) } } else { - static bool error_printed = false; - if (not error_printed) { - etiLog.level(warn) << - "Your platform doesn't seem to have hardware concurrency. " - "MemlessPoly will run single-threaded"; - } - // For some reason we don't have hw concurrency. apply_coeff(m_coefs, in, 0, sizeOut, out); } } diff --git a/src/MemlessPoly.h b/src/MemlessPoly.h index 9fe19d7..b7fd81e 100644 --- a/src/MemlessPoly.h +++ b/src/MemlessPoly.h @@ -52,7 +52,7 @@ typedef std::complex complexf; class MemlessPoly : public PipelinedModCodec, public RemoteControllable { public: - MemlessPoly(const std::string& coefs_file); + MemlessPoly(const std::string& coefs_file, unsigned int num_threads); virtual const char* name() { return "MemlessPoly"; } @@ -67,6 +67,7 @@ private: int internal_process(Buffer* const dataIn, Buffer* dataOut); void load_coefficients(const std::string &coefFile); + unsigned int m_num_threads; std::vector m_coefs; std::string m_coefs_file; mutable std::mutex m_coefs_mutex; -- cgit v1.2.3