summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/include
diff options
context:
space:
mode:
authorghostop14 <ghostop14@gmail.com>2020-01-29 17:20:16 -0500
committerMichael Dickens <michael.dickens@ettus.com>2020-02-14 10:05:12 -0500
commitaa0bd44efbf8afdfd93d627e486c1427426b76f9 (patch)
treedd2acb4ebed83dc5a553678ba46b76424690b90a /gnuradio-runtime/include
parent36680f338e0b7ae7e5bcf7d2a860527ca7b14dfe (diff)
gr-digital: Improve Performance of Costas Loop
This update is focused on improving the throughput of the Costas loop, however some changes are more global performance enhancements as this PR has evolved. Updates include an ENABLE_NATIVE added to CMake, which is off by default but enables native compiling (including FMA support) if desired; sincos was inlined in sincos.h and sincos.cc was removed from the appropriate CMake to improve sincos speed, some constants were added to math.h, inlined functions in costas loop and nco.h, used switch instead of function pointer (much faster), and used fast complex multiply to get around all the range checking in the standard complex.h complex multiply function on all builds.
Diffstat (limited to 'gnuradio-runtime/include')
-rw-r--r--gnuradio-runtime/include/gnuradio/math.h25
-rw-r--r--gnuradio-runtime/include/gnuradio/nco.h26
-rw-r--r--gnuradio-runtime/include/gnuradio/sincos.h42
3 files changed, 63 insertions, 30 deletions
diff --git a/gnuradio-runtime/include/gnuradio/math.h b/gnuradio-runtime/include/gnuradio/math.h
index c0e1a7dc88..f628a5875c 100644
--- a/gnuradio-runtime/include/gnuradio/math.h
+++ b/gnuradio-runtime/include/gnuradio/math.h
@@ -31,12 +31,30 @@
#define GR_M_LOG2E 1.4426950408889634074 /* log_2 e */
#define GR_M_PI 3.14159265358979323846 /* pi */
#define GR_M_PI_4 0.78539816339744830961566084582 /* pi/4 */
-#define GR_M_TWOPI (2 * GR_M_PI) /* 2*pi */
+#define GR_M_TWOPI 6.28318530717958647692 /* 2*pi */
#define GR_M_SQRT2 1.41421356237309504880 /* sqrt(2) */
+#define GR_M_ONE_OVER_2PI 0.15915494309189533577 /* 1 / (2*pi) */
+#define GR_M_MINUS_TWO_PI -6.28318530717958647692 /* - 2*pi */
namespace gr {
+static inline void
+fast_cc_multiply(gr_complex& out, const gr_complex cc1, const gr_complex cc2)
+{
+ // The built-in complex.h multiply has significant NaN/INF checking that
+ // considerably slows down performance. While on some compilers the
+ // -fcx-limit-range flag can be used, this fast function makes the math consistent
+ // in terms of performance for the Costas loop.
+ float o_r, o_i;
+
+ o_r = (cc1.real() * cc2.real()) - (cc1.imag() * cc2.imag());
+ o_i = (cc1.real() * cc2.imag()) + (cc1.imag() * cc2.real());
+
+ out.real(o_r);
+ out.imag(o_i);
+}
+
static inline bool is_power_of_2(long x) { return x != 0 && (x & (x - 1)) == 0; }
/*!
@@ -62,10 +80,7 @@ static inline float fast_atan2f(gr_complex z) { return fast_atan2f(z.imag(), z.r
/* This bounds x by +/- clip without a branch */
static inline float branchless_clip(float x, float clip)
{
- float x1 = fabsf(x + clip);
- float x2 = fabsf(x - clip);
- x1 -= x2;
- return 0.5 * x1;
+ return 0.5 * (std::abs(x + clip) - std::abs(x - clip));
}
static inline float clip(float x, float clip)
diff --git a/gnuradio-runtime/include/gnuradio/nco.h b/gnuradio-runtime/include/gnuradio/nco.h
index 6542fe58de..4bcdfe686b 100644
--- a/gnuradio-runtime/include/gnuradio/nco.h
+++ b/gnuradio-runtime/include/gnuradio/nco.h
@@ -44,27 +44,15 @@ public:
void adjust_freq(double delta_angle_rate) { phase_inc += delta_angle_rate; }
// increment current phase angle
- void step()
- {
- phase += phase_inc;
- if (fabs(phase) > GR_M_PI) {
- while (phase > GR_M_PI)
- phase -= 2 * GR_M_PI;
-
- while (phase < -GR_M_PI)
- phase += 2 * GR_M_PI;
- }
- }
-
- void step(int n)
+ void step(int n = 1)
{
phase += phase_inc * n;
if (fabs(phase) > GR_M_PI) {
while (phase > GR_M_PI)
- phase -= 2 * GR_M_PI;
+ phase -= GR_M_TWOPI;
while (phase < -GR_M_PI)
- phase += 2 * GR_M_PI;
+ phase += GR_M_TWOPI;
}
}
@@ -73,7 +61,7 @@ public:
double get_freq() const { return phase_inc; }
// compute sin and cos for current phase angle
- void sincos(float* sinx, float* cosx) const;
+ void sincos(float* sinx, float* cosx) const { gr::sincosf(phase, sinx, cosx); }
// compute cos or sin for current phase angle
float cos() const { return std::cos(phase); }
@@ -94,12 +82,6 @@ protected:
};
template <class o_type, class i_type>
-void nco<o_type, i_type>::sincos(float* sinx, float* cosx) const
-{
- gr::sincosf(phase, sinx, cosx);
-}
-
-template <class o_type, class i_type>
void nco<o_type, i_type>::sin(float* output, int noutput_items, double ampl)
{
for (int i = 0; i < noutput_items; i++) {
diff --git a/gnuradio-runtime/include/gnuradio/sincos.h b/gnuradio-runtime/include/gnuradio/sincos.h
index 15241195d0..cd0f6eb0dd 100644
--- a/gnuradio-runtime/include/gnuradio/sincos.h
+++ b/gnuradio-runtime/include/gnuradio/sincos.h
@@ -12,12 +12,48 @@
#define INCLUDED_GR_SINCOS_H
#include <gnuradio/api.h>
+#include <cmath>
namespace gr {
-// compute sine and cosine at the same time
-GR_RUNTIME_API void sincos(double x, double* sin, double* cos);
-GR_RUNTIME_API void sincosf(float x, float* sin, float* cos);
+#if defined(HAVE_SINCOS)
+
+inline void sincos(double x, double* sinx, double* cosx) { ::sincos(x, sinx, cosx); }
+
+#else
+
+inline void sincos(double x, double* sinx, double* cosx)
+{
+ *sinx = ::sin(x);
+ *cosx = ::cos(x);
+}
+
+#endif
+
+// ----------------------------------------------------------------
+
+#if defined(HAVE_SINCOSF)
+
+inline void sincosf(float x, float* sinx, float* cosx) { ::sincosf(x, sinx, cosx); }
+
+#elif defined(HAVE_SINF) && defined(HAVE_COSF)
+
+inline void sincosf(float x, float* sinx, float* cosx)
+{
+ *sinx = ::sinf(x);
+ *cosx = ::cosf(x);
+}
+
+#else
+
+inline void sincosf(float x, float* sinx, float* cosx)
+{
+ *sinx = ::sin(x);
+ *cosx = ::cos(x);
+}
+
+#endif
+
} // namespace gr
#endif /* INCLUDED_GR_SINCOS_H */