summaryrefslogtreecommitdiff
path: root/gnuradio-core/src
diff options
context:
space:
mode:
authorTom Rondeau2012-02-06 14:48:13 -0500
committerTom Rondeau2012-02-06 14:48:13 -0500
commitc4d0b47fdbbbfee18d6dfc87c501731a0591fa57 (patch)
tree99e8c564bfa7f717ecba0f62bb356b92034d2efc /gnuradio-core/src
parentf49facf71cd1b31a8553de85377d956a3299f2d7 (diff)
parent7e10a26470d638afec9db3bd89ae3243fe0abd83 (diff)
downloadgnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.tar.gz
gnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.tar.bz2
gnuradio-c4d0b47fdbbbfee18d6dfc87c501731a0591fa57.zip
Merge branch 'master' into next
Diffstat (limited to 'gnuradio-core/src')
-rw-r--r--gnuradio-core/src/lib/CMakeLists.txt5
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.cc29
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.h22
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_ccc.i10
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.cc28
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.h24
-rw-r--r--gnuradio-core/src/lib/filter/gr_fft_filter_fff.i9
-rw-r--r--gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.cc25
-rw-r--r--gnuradio-core/src/lib/filter/gri_fft_filter_ccc_generic.h15
-rw-r--r--gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.cc21
-rw-r--r--gnuradio-core/src/lib/filter/gri_fft_filter_fff_generic.h15
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc.cc20
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc.h11
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc.i10
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc_fftw.cc27
-rw-r--r--gnuradio-core/src/lib/general/gr_fft_vcc_fftw.h15
-rw-r--r--gnuradio-core/src/lib/general/gri_fft.cc70
-rw-r--r--gnuradio-core/src/lib/general/gri_fft.h39
-rw-r--r--gnuradio-core/src/lib/io/gr_oscope_guts.cc3
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_fft.py54
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gr/qa_fft_filter.py86
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):