diff options
author | Tom Rondeau | 2012-02-06 14:48:13 -0500 |
---|---|---|
committer | Tom Rondeau | 2012-02-06 14:48:13 -0500 |
commit | c4d0b47fdbbbfee18d6dfc87c501731a0591fa57 (patch) | |
tree | 99e8c564bfa7f717ecba0f62bb356b92034d2efc /gnuradio-core/src | |
parent | f49facf71cd1b31a8553de85377d956a3299f2d7 (diff) | |
parent | 7e10a26470d638afec9db3bd89ae3243fe0abd83 (diff) | |
download | gnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.tar.gz gnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.tar.bz2 gnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.zip |
Merge branch 'master' into next
Diffstat (limited to 'gnuradio-core/src')
21 files changed, 485 insertions, 53 deletions
diff --git a/gnuradio-core/src/lib/CMakeLists.txt b/gnuradio-core/src/lib/CMakeLists.txt index 52339fc6c..3fbe8f807 100644 --- a/gnuradio-core/src/lib/CMakeLists.txt +++ b/gnuradio-core/src/lib/CMakeLists.txt @@ -63,6 +63,11 @@ list(APPEND gnuradio_core_libs ${FFTW3F_LIBRARIES} ) +if(FFTW3F_THREADS_LIBRARIES) + list(APPEND gnuradio_core_libs ${FFTW3F_THREADS_LIBRARIES} ) + add_definitions("-DFFTW3F_THREADS") +endif() + #need to link with librt on ubuntu 11.10 for shm_* if(LINUX) list(APPEND gnuradio_core_libs rt) 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/lib/general/gr_fft_vcc.cc b/gnuradio-core/src/lib/general/gr_fft_vcc.cc index d07f6fa07..64dda2491 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.cc +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.cc @@ -32,9 +32,12 @@ #include <string.h> gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward,const std::vector<float> &window, bool shift) +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) { - return gr_make_fft_vcc_fftw(fft_size, forward, window, shift); + return gr_make_fft_vcc_fftw(fft_size, forward, + window, shift, nthreads); } gr_fft_vcc::gr_fft_vcc (const std::string &name, @@ -62,3 +65,16 @@ gr_fft_vcc::set_window(const std::vector<float> &window) else return false; } + +void +gr_fft_vcc::set_nthreads(int n) +{ + throw std::runtime_error("gr_fft_vcc::set_nthreads not implemented."); +} + +int +gr_fft_vcc::nthreads() const +{ + throw std::runtime_error("gr_fft_vcc::nthreads not implemented."); + return 0; +} diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.h b/gnuradio-core/src/lib/general/gr_fft_vcc.h index a7c8e1162..6c3985987 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.h +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.h @@ -30,7 +30,9 @@ class gr_fft_vcc; typedef boost::shared_ptr<gr_fft_vcc> gr_fft_vcc_sptr; GR_CORE_API gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); /*! * \brief Compute forward or reverse FFT. complex vector in / complex vector out. @@ -42,7 +44,9 @@ class GR_CORE_API gr_fft_vcc : public gr_sync_block { protected: friend GR_CORE_API gr_fft_vcc_sptr - gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); unsigned int d_fft_size; std::vector<float> d_window; @@ -55,6 +59,9 @@ protected: public: ~gr_fft_vcc (); + virtual void set_nthreads(int n); + virtual int nthreads() const; + bool set_window(const std::vector<float> &window); }; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc.i b/gnuradio-core/src/lib/general/gr_fft_vcc.i index f35316e70..0dc5353b2 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc.i +++ b/gnuradio-core/src/lib/general/gr_fft_vcc.i @@ -23,13 +23,19 @@ GR_SWIG_BLOCK_MAGIC(gr, fft_vcc) gr_fft_vcc_sptr -gr_make_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); class gr_fft_vcc : public gr_sync_block { protected: - gr_fft_vcc (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_fft_vcc (int fft_size, bool forward, + const std::vector<float> &window, + bool shift); public: bool set_window(const std::vector<float> &window); + void set_nthreads(int n); + int nthreads() const; }; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc index 948ab20b9..e6032ad9e 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc @@ -31,16 +31,21 @@ #include <string.h> gr_fft_vcc_sptr -gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift) +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads) { - return gnuradio::get_initial_sptr(new gr_fft_vcc_fftw (fft_size, forward, window, shift)); + return gnuradio::get_initial_sptr(new gr_fft_vcc_fftw + (fft_size, forward, window, + shift, nthreads)); } gr_fft_vcc_fftw::gr_fft_vcc_fftw (int fft_size, bool forward, - const std::vector<float> &window, bool shift) + const std::vector<float> &window, + bool shift, int nthreads) : gr_fft_vcc("fft_vcc_fftw", fft_size, forward, window, shift) { - d_fft = new gri_fft_complex (d_fft_size, forward); + d_fft = new gri_fft_complex (d_fft_size, forward, nthreads); } gr_fft_vcc_fftw::~gr_fft_vcc_fftw () @@ -48,6 +53,18 @@ gr_fft_vcc_fftw::~gr_fft_vcc_fftw () delete d_fft; } +void +gr_fft_vcc_fftw::set_nthreads(int n) +{ + d_fft->set_nthreads(n); +} + +int +gr_fft_vcc_fftw::nthreads() const +{ + return d_fft->nthreads(); +} + int gr_fft_vcc_fftw::work (int noutput_items, gr_vector_const_void_star &input_items, @@ -70,7 +87,7 @@ gr_fft_vcc_fftw::work (int noutput_items, if(!d_forward && d_shift){ int offset = (!d_forward && d_shift)?(d_fft_size/2):0; int fft_m_offset = d_fft_size - offset; - for (unsigned int i = 0; i < offset; i++) // apply window + for (int i = 0; i < offset; i++) // apply window dst[i+fft_m_offset] = in[i] * d_window[i]; for (unsigned int i = offset; i < d_fft_size; i++) // apply window dst[i-offset] = in[i] * d_window[i]; diff --git a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h index 8535d133c..82b7512d7 100644 --- a/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h +++ b/gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h @@ -29,7 +29,9 @@ class gri_fft_complex; GR_CORE_API gr_fft_vcc_sptr -gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift=false); +gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift=false, int nthreads=1); /*! * \brief Compute forward or reverse FFT. complex vector in / complex vector out. @@ -40,15 +42,22 @@ gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &wind class GR_CORE_API gr_fft_vcc_fftw : public gr_fft_vcc { friend GR_CORE_API gr_fft_vcc_sptr - gr_make_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_make_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads); gri_fft_complex *d_fft; - gr_fft_vcc_fftw (int fft_size, bool forward, const std::vector<float> &window, bool shift); + gr_fft_vcc_fftw (int fft_size, bool forward, + const std::vector<float> &window, + bool shift, int nthreads=1); public: ~gr_fft_vcc_fftw (); + void set_nthreads(int n); + 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/general/gri_fft.cc b/gnuradio-core/src/lib/general/gri_fft.cc index 0df1af25d..63e307776 100644 --- a/gnuradio-core/src/lib/general/gri_fft.cc +++ b/gnuradio-core/src/lib/general/gri_fft.cc @@ -78,6 +78,22 @@ gri_fftw_import_wisdom () } static void +gri_fftw_config_threading (int nthreads) +{ + static int fftw_threads_inited = 0; + +#ifdef FFTW3F_THREADS + if (fftw_threads_inited == 0) + { + fftw_threads_inited = 1; + fftwf_init_threads(); + } + + fftwf_plan_with_nthreads(nthreads); +#endif +} + +static void gri_fftw_export_wisdom () { const char *filename = wisdom_filename (); @@ -94,7 +110,7 @@ gri_fftw_export_wisdom () // ---------------------------------------------------------------- -gri_fft_complex::gri_fft_complex (int fft_size, bool forward) +gri_fft_complex::gri_fft_complex (int fft_size, bool forward, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -115,7 +131,10 @@ gri_fft_complex::gri_fft_complex (int fft_size, bool forward) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_1d (fft_size, reinterpret_cast<fftwf_complex *>(d_inbuf), reinterpret_cast<fftwf_complex *>(d_outbuf), @@ -139,6 +158,18 @@ gri_fft_complex::~gri_fft_complex () fftwf_free (d_outbuf); } +void +gri_fft_complex::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_complex::execute () { @@ -147,7 +178,7 @@ gri_fft_complex::execute () // ---------------------------------------------------------------- -gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) +gri_fft_real_fwd::gri_fft_real_fwd (int fft_size, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -168,7 +199,10 @@ gri_fft_real_fwd::gri_fft_real_fwd (int fft_size) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); gri_fftw_import_wisdom (); // load prior wisdom from disk + d_plan = fftwf_plan_dft_r2c_1d (fft_size, d_inbuf, reinterpret_cast<fftwf_complex *>(d_outbuf), @@ -191,6 +225,18 @@ gri_fft_real_fwd::~gri_fft_real_fwd () fftwf_free (d_outbuf); } +void +gri_fft_real_fwd::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_real_fwd::execute () { @@ -199,7 +245,7 @@ gri_fft_real_fwd::execute () // ---------------------------------------------------------------- -gri_fft_real_rev::gri_fft_real_rev (int fft_size) +gri_fft_real_rev::gri_fft_real_rev (int fft_size, int nthreads) { // Hold global mutex during plan construction and destruction. gri_fft_planner::scoped_lock lock(gri_fft_planner::mutex()); @@ -220,11 +266,13 @@ gri_fft_real_rev::gri_fft_real_rev (int fft_size) throw std::runtime_error ("fftwf_malloc"); } + d_nthreads = nthreads; + gri_fftw_config_threading (nthreads); + gri_fftw_import_wisdom (); // load prior wisdom from disk + // FIXME If there's ever a chance that the planning functions // will be called in multiple threads, we've got to ensure single // threaded access. They are not thread-safe. - - gri_fftw_import_wisdom (); // load prior wisdom from disk d_plan = fftwf_plan_dft_c2r_1d (fft_size, reinterpret_cast<fftwf_complex *>(d_inbuf), d_outbuf, @@ -244,6 +292,18 @@ gri_fft_real_rev::~gri_fft_real_rev () fftwf_free (d_outbuf); } +void +gri_fft_real_rev::set_nthreads(int n) +{ + if (n <= 0) + throw std::out_of_range ("gri_fftw: invalid number of threads"); + d_nthreads = n; + +#ifdef FFTW3F_THREADS + fftwf_plan_with_nthreads(d_nthreads); +#endif +} + void gri_fft_real_rev::execute () { diff --git a/gnuradio-core/src/lib/general/gri_fft.h b/gnuradio-core/src/lib/general/gri_fft.h index 91a82fb55..ed80badf1 100644 --- a/gnuradio-core/src/lib/general/gri_fft.h +++ b/gnuradio-core/src/lib/general/gri_fft.h @@ -49,12 +49,13 @@ public: */ class GR_CORE_API gri_fft_complex { int d_fft_size; + int d_nthreads; gr_complex *d_inbuf; gr_complex *d_outbuf; void *d_plan; public: - gri_fft_complex (int fft_size, bool forward = true); + gri_fft_complex (int fft_size, bool forward = true, int nthreads=1); virtual ~gri_fft_complex (); /* @@ -69,6 +70,16 @@ public: int outbuf_length () const { return d_fft_size; } /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! * compute FFT. The input comes from inbuf, the output is placed in outbuf. */ void execute (); @@ -80,12 +91,13 @@ public: */ class GR_CORE_API gri_fft_real_fwd { int d_fft_size; + int d_nthreads; float *d_inbuf; gr_complex *d_outbuf; void *d_plan; public: - gri_fft_real_fwd (int fft_size); + gri_fft_real_fwd (int fft_size, int nthreads=1); virtual ~gri_fft_real_fwd (); /* @@ -100,6 +112,16 @@ public: int outbuf_length () const { return d_fft_size / 2 + 1; } /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! * compute FFT. The input comes from inbuf, the output is placed in outbuf. */ void execute (); @@ -111,12 +133,13 @@ public: */ class GR_CORE_API gri_fft_real_rev { int d_fft_size; + int d_nthreads; gr_complex *d_inbuf; float *d_outbuf; void *d_plan; public: - gri_fft_real_rev (int fft_size); + gri_fft_real_rev (int fft_size, int nthreads=1); virtual ~gri_fft_real_rev (); /* @@ -131,6 +154,16 @@ public: int outbuf_length () const { return d_fft_size; } /*! + * Set the number of threads to use for caclulation. + */ + void set_nthreads(int n); + + /*! + * Get the number of threads being used by FFTW + */ + int nthreads() const { return d_nthreads; } + + /*! * compute FFT. The input comes from inbuf, the output is placed in outbuf. */ void execute (); diff --git a/gnuradio-core/src/lib/io/gr_oscope_guts.cc b/gnuradio-core/src/lib/io/gr_oscope_guts.cc index f1bdeb9c1..7bdc53ab0 100644 --- a/gnuradio-core/src/lib/io/gr_oscope_guts.cc +++ b/gnuradio-core/src/lib/io/gr_oscope_guts.cc @@ -31,7 +31,7 @@ #include <math.h> #include <assert.h> -static const int OUTPUT_RECORD_SIZE = 16384; // Must be power of 2 +static const int OUTPUT_RECORD_SIZE = 8192; // Must be power of 2 static inline int wrap_bi (int buffer_index) // wrap buffer index { @@ -144,6 +144,7 @@ gr_oscope_guts::process_sample (const float *channel_data) } d_buffer[i][0] = channel_data[i]; } + d_trigger_off = 0; write_output_records(); } } diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_fft.py b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py index 98d80fbb0..e90eb2e7f 100755 --- a/gnuradio-core/src/python/gnuradio/gr/qa_fft.py +++ b/gnuradio-core/src/python/gnuradio/gr/qa_fft.py @@ -152,6 +152,60 @@ class test_fft(gr_unittest.TestCase): #self.assertComplexTuplesAlmostEqual (expected_result, result_data, 5) self.assert_fft_ok2(expected_result, result_data) + def test_003(self): + # Same test as above, only use 2 threads + + tb = gr.top_block() + fft_size = 32 + + tmp_data = ((4377+4516j), + (-1706.1268310546875+1638.4256591796875j), + (-915.2083740234375+660.69427490234375j), + (-660.370361328125+381.59600830078125j), + (-499.96044921875+238.41630554199219j), + (-462.26748657226562+152.88948059082031j), + (-377.98440551757812+77.5928955078125j), + (-346.85821533203125+47.152004241943359j), + (-295+20j), + (-286.33609008789062-22.257017135620117j), + (-271.52999877929688-33.081821441650391j), + (-224.6358642578125-67.019538879394531j), + (-244.24473571777344-91.524826049804688j), + (-203.09068298339844-108.54627227783203j), + (-198.45195007324219-115.90768432617188j), + (-182.97744750976562-128.12318420410156j), + (-167-180j), + (-130.33688354492188-173.83778381347656j), + (-141.19784545898438-190.28807067871094j), + (-111.09677124023438-214.48896789550781j), + (-70.039543151855469-242.41630554199219j), + (-68.960540771484375-228.30015563964844j), + (-53.049201965332031-291.47097778320312j), + (-28.695289611816406-317.64553833007812j), + (57-300j), + (45.301143646240234-335.69509887695312j), + (91.936195373535156-373.32437133789062j), + (172.09465026855469-439.275146484375j), + (242.24473571777344-504.47515869140625j), + (387.81732177734375-666.6788330078125j), + (689.48553466796875-918.2142333984375j), + (1646.539306640625-1694.1956787109375j)) + + src_data = tuple([x/fft_size for x in tmp_data]) + + expected_result = tuple([complex(primes[2*i], primes[2*i+1]) for i in range(fft_size)]) + + nthreads = 2 + + src = gr.vector_source_c(src_data) + s2v = gr.stream_to_vector(gr.sizeof_gr_complex, fft_size) + fft = gr.fft_vcc(fft_size, False, [], False, nthreads) + v2s = gr.vector_to_stream(gr.sizeof_gr_complex, fft_size) + dst = gr.vector_sink_c() + tb.connect(src, s2v, fft, v2s, dst) + tb.run() + result_data = dst.data() + self.assert_fft_ok2(expected_result, result_data) if __name__ == '__main__': gr_unittest.run(test_fft, "test_fft.xml") 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): |