diff options
11 files changed, 254 insertions, 30 deletions
diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc index 9fa98cc69..63b52411e 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc @@ -43,13 +43,17 @@ #include <iostream> #include <string.h> -gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) +gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_filter_ccc (decimation, taps)); + return gnuradio::get_initial_sptr(new gr_fft_filter_ccc (decimation, taps, nthreads)); } -gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps) +gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, + const std::vector<gr_complex> &taps, + int nthreads) : gr_sync_decimator ("fft_filter_ccc", gr_make_io_signature (1, 1, sizeof (gr_complex)), gr_make_io_signature (1, 1, sizeof (gr_complex)), @@ -58,7 +62,7 @@ gr_fft_filter_ccc::gr_fft_filter_ccc (int decimation, const std::vector<gr_compl { set_history(1); #if 1 // don't enable the sse version until handling it is worked out - d_filter = new gri_fft_filter_ccc_generic(decimation, taps); + d_filter = new gri_fft_filter_ccc_generic(decimation, taps, nthreads); #else d_filter = new gri_fft_filter_ccc_sse(decimation, taps); #endif @@ -85,6 +89,23 @@ gr_fft_filter_ccc::taps () const return d_new_taps; } +void +gr_fft_filter_ccc::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_ccc::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + + int gr_fft_filter_ccc::work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h index 1b72a1c00..d037597e8 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h @@ -27,7 +27,9 @@ class gr_fft_filter_ccc; typedef boost::shared_ptr<gr_fft_filter_ccc> gr_fft_filter_ccc_sptr; -GR_CORE_API gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); +GR_CORE_API gr_fft_filter_ccc_sptr +gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); //class gri_fft_filter_ccc_sse; class gri_fft_filter_ccc_generic; @@ -39,7 +41,9 @@ class gri_fft_filter_ccc_generic; class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator { private: - friend GR_CORE_API gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + friend GR_CORE_API gr_fft_filter_ccc_sptr + gr_make_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads); int d_nsamples; bool d_updated; @@ -55,8 +59,10 @@ class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator * * \param decimation >= 1 * \param taps complex filter taps + * \param nthreads number of threads for the FFT to use */ - gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); public: ~gr_fft_filter_ccc (); @@ -64,6 +70,16 @@ class GR_CORE_API gr_fft_filter_ccc : public gr_sync_decimator void set_taps (const std::vector<gr_complex> &taps); std::vector<gr_complex> taps () const; + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i index 812920d8b..acdc347a6 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i @@ -24,17 +24,23 @@ GR_SWIG_BLOCK_MAGIC(gr,fft_filter_ccc) gr_fft_filter_ccc_sptr gr_make_fft_filter_ccc (int decimation, - const std::vector<gr_complex> &taps + const std::vector<gr_complex> &taps, + int nthreads=1 ) throw (std::invalid_argument); class gr_fft_filter_ccc : public gr_sync_decimator { private: - gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps); + gr_fft_filter_ccc (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); public: ~gr_fft_filter_ccc (); void set_taps (const std::vector<gr_complex> &taps); std::vector<gr_complex> taps () const; + + void set_nthreads(int n); + int nthreads() const; + }; diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc index c0a9b3483..0e4072f63 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc @@ -35,13 +35,17 @@ #include <iostream> #include <string.h> -gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps) +gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps)); + return gnuradio::get_initial_sptr(new gr_fft_filter_fff (decimation, taps, nthreads)); } -gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> &taps) +gr_fft_filter_fff::gr_fft_filter_fff (int decimation, + const std::vector<float> &taps, + int nthreads) : gr_sync_decimator ("fft_filter_fff", gr_make_io_signature (1, 1, sizeof (float)), gr_make_io_signature (1, 1, sizeof (float)), @@ -51,7 +55,7 @@ gr_fft_filter_fff::gr_fft_filter_fff (int decimation, const std::vector<float> & set_history(1); #if 1 // don't enable the sse version until handling it is worked out - d_filter = new gri_fft_filter_fff_generic(decimation, taps); + d_filter = new gri_fft_filter_fff_generic(decimation, taps, nthreads); #else d_filter = new gri_fft_filter_fff_sse(decimation, taps); #endif @@ -78,6 +82,22 @@ gr_fft_filter_fff::taps () const return d_new_taps; } +void +gr_fft_filter_fff::set_nthreads(int n) +{ + if(d_filter) + d_filter->set_nthreads(n); +} + +int +gr_fft_filter_fff::nthreads() const +{ + if(d_filter) + return d_filter->nthreads(); + else + return 0; +} + int gr_fft_filter_fff::work (int noutput_items, gr_vector_const_void_star &input_items, diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h index ddd8dcac2..2eeb8c646 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.h @@ -27,7 +27,9 @@ class gr_fft_filter_fff; typedef boost::shared_ptr<gr_fft_filter_fff> gr_fft_filter_fff_sptr; -GR_CORE_API gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); +GR_CORE_API gr_fft_filter_fff_sptr +gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); class gri_fft_filter_fff_generic; //class gri_fft_filter_fff_sse; @@ -39,7 +41,9 @@ class gri_fft_filter_fff_generic; class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator { private: - friend GR_CORE_API gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps); + friend GR_CORE_API gr_fft_filter_fff_sptr + gr_make_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads); int d_nsamples; bool d_updated; @@ -55,15 +59,27 @@ class GR_CORE_API gr_fft_filter_fff : public gr_sync_decimator * * \param decimation >= 1 * \param taps float filter taps + * \param nthreads number of threads for the FFT to use */ - gr_fft_filter_fff (int decimation, const std::vector<float> &taps); - + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); + public: ~gr_fft_filter_fff (); void set_taps (const std::vector<float> &taps); std::vector<float> taps () const; + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + int work (int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); diff --git a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i index 7e2cde977..c8118e09e 100644 --- a/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i +++ b/gnuradio-core/src/lib/filter/gr_fft_filter_fff.i @@ -24,17 +24,22 @@ GR_SWIG_BLOCK_MAGIC(gr,fft_filter_fff) gr_fft_filter_fff_sptr gr_make_fft_filter_fff (int decimation, - const std::vector<float> &taps + const std::vector<float> &taps, + int nthreads=1 ) throw (std::invalid_argument); class gr_fft_filter_fff : public gr_sync_decimator { private: - gr_fft_filter_fff (int decimation, const std::vector<float> &taps); + gr_fft_filter_fff (int decimation, const std::vector<float> &taps, + int nthreads=1); public: ~gr_fft_filter_fff (); void set_taps (const std::vector<float> &taps); std::vector<float> taps () const; + void set_nthreads(int n); + int nthreads() const; + }; diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc index 891905dd0..47e18b3e3 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc @@ -33,8 +33,9 @@ #include <fftw3.h> gri_fft_filter_ccc_generic::gri_fft_filter_ccc_generic (int decimation, - const std::vector<gr_complex> &taps) - : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) + const std::vector<gr_complex> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) { set_taps(taps); } @@ -111,12 +112,28 @@ gri_fft_filter_ccc_generic::compute_sizes(int ntaps) if (d_fftsize != old_fftsize){ // compute new plans delete d_fwdfft; delete d_invfft; - d_fwdfft = new gri_fft_complex(d_fftsize, true); - d_invfft = new gri_fft_complex(d_fftsize, false); + d_fwdfft = new gri_fft_complex(d_fftsize, true, d_nthreads); + d_invfft = new gri_fft_complex(d_fftsize, false, d_nthreads); d_xformed_taps.resize(d_fftsize); } } +void +gri_fft_filter_ccc_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_ccc_generic::nthreads() const +{ + return d_nthreads; +} + int gri_fft_filter_ccc_generic::filter (int nitems, const gr_complex *input, gr_complex *output) { diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h index 4db7ba50f..217b9ab83 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h @@ -42,6 +42,7 @@ class GR_CORE_API gri_fft_filter_ccc_generic int d_decimation; gri_fft_complex *d_fwdfft; // forward "plan" gri_fft_complex *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<gr_complex> d_tail; // state carried between blocks for overlap-add std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps std::vector<gr_complex> d_new_taps; @@ -57,8 +58,10 @@ class GR_CORE_API gri_fft_filter_ccc_generic * in other blocks for complex vectors (such as gr_fft_filter_ccc). * \param decimation The decimation rate of the filter (int) * \param taps The filter taps (complex) + * \param nthreads The number of threads for the FFT to use (int) */ - gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps); + gri_fft_filter_ccc_generic (int decimation, const std::vector<gr_complex> &taps, + int nthreads=1); ~gri_fft_filter_ccc_generic (); /*! @@ -68,6 +71,16 @@ class GR_CORE_API gri_fft_filter_ccc_generic * \param taps The filter taps (complex) */ int set_taps (const std::vector<gr_complex> &taps); + + /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; /*! * \brief Perform the filter operation diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc index b3fbe1d1a..598bf268c 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc @@ -32,8 +32,9 @@ #include <cstring> gri_fft_filter_fff_generic::gri_fft_filter_fff_generic (int decimation, - const std::vector<float> &taps) - : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0) + const std::vector<float> &taps, + int nthreads) + : d_fftsize(-1), d_decimation(decimation), d_fwdfft(0), d_invfft(0), d_nthreads(nthreads) { set_taps(taps); } @@ -104,6 +105,22 @@ gri_fft_filter_fff_generic::compute_sizes(int ntaps) } } +void +gri_fft_filter_fff_generic::set_nthreads(int n) +{ + d_nthreads = n; + if(d_fwdfft) + d_fwdfft->set_nthreads(n); + if(d_invfft) + d_invfft->set_nthreads(n); +} + +int +gri_fft_filter_fff_generic::nthreads() const +{ + return d_nthreads; +} + int gri_fft_filter_fff_generic::filter (int nitems, const float *input, float *output) { diff --git a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h index 86658043a..be31068aa 100644 --- a/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h +++ b/gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h @@ -39,6 +39,7 @@ class GR_CORE_API gri_fft_filter_fff_generic int d_decimation; gri_fft_real_fwd *d_fwdfft; // forward "plan" gri_fft_real_rev *d_invfft; // inverse "plan" + int d_nthreads; // number of FFTW threads to use std::vector<float> d_tail; // state carried between blocks for overlap-add std::vector<gr_complex> d_xformed_taps; // Fourier xformed taps std::vector<float> d_new_taps; @@ -55,8 +56,10 @@ class GR_CORE_API gri_fft_filter_fff_generic * in other blocks for floating point vectors (such as gr_fft_filter_fff). * \param decimation The decimation rate of the filter (int) * \param taps The filter taps (float) + * \param nthreads The number of threads for the FFT to use (int) */ - gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps); + gri_fft_filter_fff_generic (int decimation, const std::vector<float> &taps, + int nthreads=1); ~gri_fft_filter_fff_generic (); /*! @@ -68,6 +71,16 @@ class GR_CORE_API gri_fft_filter_fff_generic int set_taps (const std::vector<float> &taps); /*! + * \brief Set number of threads to use. + */ + void set_nthreads(int n); + + /*! + * \brief Get number of threads being used. + */ + int nthreads() const; + + /*! * \brief Perform the filter operation * * \param nitems The number of items to produce diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py index 325495c1d..1e9fdb6a8 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py @@ -110,6 +110,23 @@ class test_fft_filter(gr_unittest.TestCase): def test_ccc_002(self): + # Test nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * complex(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(1, taps, nthreads) + dst = gr.vector_sink_c() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + #print 'expected:', expected_result + #print 'results: ', result_data + self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + + def test_ccc_003(self): tb = gr.top_block() src_data = (0,1,2,3,4,5,6,7) taps = (2,) @@ -124,6 +141,7 @@ class test_fft_filter(gr_unittest.TestCase): #print 'results: ', result_data self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) + def test_ccc_004(self): random.seed(0) for i in xrange(25): @@ -167,6 +185,30 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_ok2(expected_result, result_data) + def test_ccc_006(self): + # Test decimating with nthreads=2 + random.seed(0) + nthreads = 2 + for i in xrange(25): + # sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_complex_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_complex_tuple(ntaps) + expected_result = reference_filter_ccc(dec, taps, src_data) + + src = gr.vector_source_c(src_data) + op = gr.fft_filter_ccc(dec, taps, nthreads) + dst = gr.vector_sink_c() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + del tb + result_data = dst.data() + + self.assert_fft_ok2(expected_result, result_data) + # ---------------------------------------------------------------- # test _fff version # ---------------------------------------------------------------- @@ -202,7 +244,22 @@ class test_fft_filter(gr_unittest.TestCase): #print 'results: ', result_data self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) - def xtest_fff_003(self): + def test_fff_003(self): + # Test 02 with nthreads + tb = gr.top_block() + src_data = (0,1,2,3,4,5,6,7) + taps = (2,) + nthreads = 2 + expected_result = tuple([2 * float(x) for x in (0,1,2,3,4,5,6,7)]) + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(1, taps, nthreads) + dst = gr.vector_sink_f() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + self.assertFloatTuplesAlmostEqual (expected_result, result_data, 5) + + def xtest_fff_004(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -232,7 +289,7 @@ class test_fft_filter(gr_unittest.TestCase): actual.write(`x` + '\n') raise - def xtest_fff_004(self): + def xtest_fff_005(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -252,7 +309,7 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_float_ok2(expected_result, result_data, abs_eps=2.0) - def xtest_fff_005(self): + def xtest_fff_006(self): random.seed(0) for i in xrange(25): sys.stderr.write("\n>>> Loop = %d\n" % (i,)) @@ -273,6 +330,29 @@ class test_fft_filter(gr_unittest.TestCase): self.assert_fft_float_ok2(expected_result, result_data) + def xtest_fff_007(self): + # test decimation with nthreads + random.seed(0) + nthreads = 2 + for i in xrange(25): + sys.stderr.write("\n>>> Loop = %d\n" % (i,)) + dec = i + 1 + src_len = 4*1024 + src_data = make_random_float_tuple(src_len) + ntaps = int(random.uniform(2, 100)) + taps = make_random_float_tuple(ntaps) + expected_result = reference_filter_fff(dec, taps, src_data) + + src = gr.vector_source_f(src_data) + op = gr.fft_filter_fff(dec, taps, nthreads) + dst = gr.vector_sink_f() + tb = gr.top_block() + tb.connect(src, op, dst) + tb.run() + result_data = dst.data() + + self.assert_fft_float_ok2(expected_result, result_data) + def test_fff_get0(self): random.seed(0) for i in xrange(25): |