changeset 4:2d6c49fcafcb

neon2 and neon4 support
author Peter Meerwald <p.meerwald@bct-electronic.com>
date Fri, 16 Sep 2011 14:04:19 +0200
parents 3b31bd44a09f
children c7237a7544eb
files _peck_fft_guts.h compile.sh peck_fft.c peck_fft.h peck_fftr.c peck_test.c
diffstat 6 files changed, 109 insertions(+), 72 deletions(-) [+]
line wrap: on
line diff
--- a/_peck_fft_guts.h	Fri Sep 16 13:08:20 2011 +0200
+++ b/_peck_fft_guts.h	Fri Sep 16 14:04:19 2011 +0200
@@ -125,17 +125,25 @@
 
 
 #ifdef FIXED_POINT
-#  define PECK_FFT_COS(phase)  floor(.5+SAMP_MAX * cos (phase))
-#  define PECK_FFT_SIN(phase)  floor(.5+SAMP_MAX * sin (phase))
-#  define HALF_OF(x) ((x)>>1)
-#elif defined(USE_SIMD)
-#  define PECK_FFT_COS(phase) _mm_set1_ps( cos(phase) )
-#  define PECK_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
-#  define HALF_OF(x) ((x)*_mm_set1_ps(.5))
+    #define PECK_FFT_COS(phase) floorf(0.5f+SAMP_MAX * cosf(phase))
+    #define PECK_FFT_SIN(phase) floorf(0.5f+SAMP_MAX * sinf(phase))
+    #define HALF_OF(x) ((x)>>1)
+#elif USE_SIMD == SIMD_SSE2
+    #define PECK_FFT_COS(phase) _mm_set1_ps(cosf(phase))
+    #define PECK_FFT_SIN(phase) _mm_set1_ps(sinf(phase))
+    #define HALF_OF(x) ((x)*_mm_set1_ps(0.5f))
+#elif USE_SIMD == SIMD_NEON4
+    #define PECK_FFT_COS(phase) vdupq_n_f32(cosf(phase))
+    #define PECK_FFT_SIN(phase) vdupq_n_f32(sinf(phase))
+    #define HALF_OF(x) ((x)*vdupq_n_f32(0.5f))
+#elif USE_SIMD == SIMD_NEON2
+    #define PECK_FFT_COS(phase) vdup_n_f32(cosf(phase))
+    #define PECK_FFT_SIN(phase) vdup_n_f32(sinf(phase))
+    #define HALF_OF(x) ((x)*vdup_n_f32(0.5f))
 #else
-#  define PECK_FFT_COS(phase) (peck_fft_scalar) cos(phase)
-#  define PECK_FFT_SIN(phase) (peck_fft_scalar) sin(phase)
-#  define HALF_OF(x) ((x)*.5)
+    #define PECK_FFT_COS(phase) (peck_fft_scalar) cosf(phase)
+    #define PECK_FFT_SIN(phase) (peck_fft_scalar) sinf(phase)
+    #define HALF_OF(x) ((x)*0.5f)
 #endif
 
 #define  kf_cexp(x,phase) \
--- a/compile.sh	Fri Sep 16 13:08:20 2011 +0200
+++ b/compile.sh	Fri Sep 16 14:04:19 2011 +0200
@@ -1,21 +1,22 @@
+
+/opt/arm-2011.03/bin/arm-none-linux-gnueabi-gcc \
+	-O3 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ffast-math -fomit-frame-pointer \
+    -DUSE_SIMD=SIMD_NEON2 \
+    -I . \
+    -o peck_test_arm \
+    peck_fftr.c peck_fft.c \
+    peck_test.c \
+    -lm 
 
 gcc \
+    -O2 -march=native -msse2 -mfpmath=sse -ffast-math -fomit-frame-pointer \
+    -DUSE_SIMD=SIMD_SSE2 \
     -I . \
     -o peck_test_x86 \
     peck_fftr.c peck_fft.c \
     peck_test.c \
     -lm 
 
-exit
+# time ./peck_test_x86
 
-/opt/arm-2011.03/bin/arm-none-linux-gnueabi-gcc \
-    -I . \
-	-O3 -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp -ffast-math -fomit-frame-pointer \
-    -o peck_test_arm \
-    peck_fftr.c peck_fft.c \
-    peck_test.c \
-    -lm 
-
-time ./peck_test_x86
-
-scp peck_test_arm root@192.168.233.114:.
+scp peck_test_arm root@192.168.233.104:.
--- a/peck_fft.c	Fri Sep 16 13:08:20 2011 +0200
+++ b/peck_fft.c	Fri Sep 16 14:04:19 2011 +0200
@@ -19,10 +19,10 @@
  */
 
 static void kf_bfly2(
-        peck_fft_cpx * Fout,
-        const size_t fstride,
-        const peck_fft_cfg st,
-        int m) {
+    peck_fft_cpx * Fout,
+    const size_t fstride,
+    const peck_fft_cfg st,
+    int m) {
 
 //printf("kf_bfly2\n");
 
@@ -44,10 +44,11 @@
 }
 
 static void kf_bfly4(
-        peck_fft_cpx * Fout,
-        const size_t fstride,
-        const peck_fft_cfg st,
-        const size_t m) {
+    peck_fft_cpx * Fout,
+    const size_t fstride,
+    const peck_fft_cfg st,
+    const size_t m) {
+
     peck_fft_cpx *tw1,*tw2,*tw3;
     peck_fft_cpx scratch[6];
     size_t k=m;
@@ -94,10 +95,11 @@
 }
 
 static void kf_bfly3(
-         peck_fft_cpx * Fout,
-         const size_t fstride,
-         const peck_fft_cfg st,
-         size_t m) {
+     peck_fft_cpx * Fout,
+     const size_t fstride,
+     const peck_fft_cfg st,
+     size_t m) {
+
      size_t k=m;
      const size_t m2 = 2*m;
      peck_fft_cpx *tw1, *tw2;
@@ -107,7 +109,6 @@
 
 printf("kf_bfly3\n");
 
-
      tw1=tw2=st->twiddles;
 
      do {
@@ -139,12 +140,11 @@
 }
 
 static void kf_bfly5(
-        peck_fft_cpx * Fout,
-        const size_t fstride,
-        const peck_fft_cfg st,
-        int m
-        )
-{
+    peck_fft_cpx * Fout,
+    const size_t fstride,
+    const peck_fft_cfg st,
+    int m
+    ) {
     peck_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
     int u;
     peck_fft_cpx scratch[13];
@@ -156,7 +156,6 @@
 
 printf("kf_bfly5\n");
 
-
     Fout0=Fout;
     Fout1=Fout0+m;
     Fout2=Fout0+2*m;
@@ -164,7 +163,7 @@
     Fout4=Fout0+4*m;
 
     tw=st->twiddles;
-    for ( u=0; u<m; ++u ) {
+    for (u = 0; u < m; ++u) {
         C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
         scratch[0] = *Fout0;
 
@@ -204,13 +203,12 @@
 
 /* perform the butterfly for one stage of a mixed radix FFT */
 static void kf_bfly_generic(
-        peck_fft_cpx * Fout,
-        const size_t fstride,
-        const peck_fft_cfg st,
-        int m,
-        int p
-        )
-{
+    peck_fft_cpx * Fout,
+    const size_t fstride,
+    const peck_fft_cfg st,
+    int m,
+    int p) {
+    
     int u,k,q1,q;
     peck_fft_cpx * twiddles = st->twiddles;
     peck_fft_cpx t;
@@ -218,7 +216,6 @@
 
 printf("kf_bfly_generic\n");
 
-
     peck_fft_cpx * scratch = (peck_fft_cpx*)PECK_FFT_TMP_ALLOC(sizeof(peck_fft_cpx)*p);
 
     for ( u=0; u<m; ++u ) {
--- a/peck_fft.h	Fri Sep 16 13:08:20 2011 +0200
+++ b/peck_fft.h	Fri Sep 16 14:04:19 2011 +0200
@@ -10,14 +10,28 @@
 extern "C" {
 #endif
 
-#ifdef USE_SIMD
-# include <xmmintrin.h>
-# define peck_fft_scalar __m128
-#define PECK_FFT_MALLOC(nbytes) _mm_malloc(nbytes, 16)
-#define PECK_FFT_FREE _mm_free
+#define SIMD_SSE2 1
+#define SIMD_NEON4 2
+#define SIMD_NEON2 3
+
+#if USE_SIMD == SIMD_SSE2
+    #include <xmmintrin.h>
+    #define peck_fft_scalar __m128
+    #define PECK_FFT_MALLOC(nbytes) _mm_malloc(nbytes, 16)
+    #define PECK_FFT_FREE _mm_free
+#elif USE_SIMD == SIMD_NEON4
+    #include <arm_neon.h>
+    #define peck_fft_scalar float32x4_t
+    #define PECK_FFT_MALLOC malloc
+    #define PECK_FFT_FREE free
+#elif USE_SIMD == SIMD_NEON2
+    #include <arm_neon.h>
+    #define peck_fft_scalar float32x2_t
+    #define PECK_FFT_MALLOC malloc
+    #define PECK_FFT_FREE free
 #else	
-#define PECK_FFT_MALLOC malloc
-#define PECK_FFT_FREE free
+    #define PECK_FFT_MALLOC malloc
+    #define PECK_FFT_FREE free
 #endif	
 
 
--- a/peck_fftr.c	Fri Sep 16 13:08:20 2011 +0200
+++ b/peck_fftr.c	Fri Sep 16 14:04:19 2011 +0200
@@ -19,8 +19,8 @@
     peck_fft_cfg substate;
     peck_fft_cpx *tmpbuf;
     peck_fft_cpx *super_twiddles;
-#ifdef USE_SIMD    
-    void * pad;
+#if USE_SIMD == SIMD_SSE2
+    void *pad;
 #endif    
 };
 
@@ -34,10 +34,9 @@
         return NULL;
     }
     nfft >>= 1;
+    peck_fft_alloc(nfft, inverse_fft, NULL, &subsize);
 
-    peck_fft_alloc(nfft, inverse_fft, NULL, &subsize);
     memneeded = sizeof(struct peck_fftr_state) + subsize + sizeof(peck_fft_cpx) * (nfft * 3 / 2);
-
     if (lenmem == NULL) {
         st = (peck_fftr_cfg) PECK_FFT_MALLOC(memneeded);
     } else {
@@ -51,6 +50,7 @@
     st->substate = (peck_fft_cfg) (st + 1); /* just beyond peck_fftr_state struct */
     st->tmpbuf = (peck_fft_cpx *) (((char *) st->substate) + subsize);
     st->super_twiddles = st->tmpbuf + nfft;
+
     peck_fft_alloc(nfft, inverse_fft, st->substate, &subsize);
 
     for (i = 0; i < nfft/2; ++i) {
@@ -60,6 +60,7 @@
             phase *= -1;
         kf_cexp(st->super_twiddles+i, phase);
     }
+
     return st;
 }
 
@@ -94,8 +95,12 @@
     CHECK_OVERFLOW_OP(tdc.r ,-, tdc.i);
     freqdata[0].r = tdc.r + tdc.i;
     freqdata[ncfft].r = tdc.r - tdc.i;
-#ifdef USE_SIMD    
+#if USE_SIMD == SIMD_SSE2
     freqdata[ncfft].i = freqdata[0].i = _mm_set1_ps(0);
+#elif USE_SIMD == SIMD_NEON4
+    freqdata[ncfft].i = freqdata[0].i = vdupq_n_f32(0.0f);
+#elif USE_SIMD == SIMD_NEON2
+    freqdata[ncfft].i = freqdata[0].i = vdup_n_f32(0.0f);
 #else
     freqdata[ncfft].i = freqdata[0].i = 0;
 #endif
@@ -138,16 +143,20 @@
         fk = freqdata[k];
         fnkc.r = freqdata[ncfft - k].r;
         fnkc.i = -freqdata[ncfft - k].i;
-        C_FIXDIV(fk , 2);
-        C_FIXDIV(fnkc , 2);
+        C_FIXDIV(fk, 2);
+        C_FIXDIV(fnkc, 2);
 
         C_ADD(fek, fk, fnkc);
         C_SUB(tmp, fk, fnkc);
         C_MUL(fok, tmp, st->super_twiddles[k-1]);
         C_ADD(st->tmpbuf[k],     fek, fok);
         C_SUB(st->tmpbuf[ncfft - k], fek, fok);
-#ifdef USE_SIMD        
-        st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0);
+#if USE_SIMD == SIMD_SSE2
+        st->tmpbuf[ncfft - k].i *= _mm_set1_ps(-1.0f);
+#elif USE_SIMD == SIMD_NEON4
+        st->tmpbuf[ncfft - k].i *= vdupq_n_f32(-1.0f);
+#elif USE_SIMD == SIMD_NEON2
+        st->tmpbuf[ncfft - k].i *= vdup_n_f32(-1.0f);
 #else
         st->tmpbuf[ncfft - k].i *= -1;
 #endif
--- a/peck_test.c	Fri Sep 16 13:08:20 2011 +0200
+++ b/peck_test.c	Fri Sep 16 14:04:19 2011 +0200
@@ -25,7 +25,7 @@
     unsigned int i, j;
     peck_fftr_cfg p, pi;
 
-    enable_runfast();
+//    enable_runfast();
 
     const unsigned int N = 256;
 
@@ -34,7 +34,15 @@
     peck_fft_scalar res[N];
 
     for (i = 0; i < N; i++) {
+#if USE_SIMD == SIMD_SSE2
+        in[i] = _mm_set1_ps((i % 13) / 3);
+#elif USE_SIMD == SIMD_NEON4
+        in[i] = vdupq_n_f32((i % 13) / 3);
+#elif USE_SIMD == SIMD_NEON2
+        in[i] = vdup_n_f32((i % 13) / 3);
+#else
         in[i] = (i % 13) / 3; 
+#endif        
     }
 
     p = peck_fftr_alloc(N, 0, NULL, NULL);
@@ -43,7 +51,7 @@
     for (j = 0; j < 10000; j++) {
         if (j == 0) {
             for (i = 0; i < 8; i++)
-                printf("%d: %f\n", i, in[i]);
+                printf("%d: %f\n", i, *(float*)&in[i]);
             printf("----\n");
         }
 
@@ -51,7 +59,7 @@
 
         if (j == 0) {
             for (i = 0; i < 8; i++)
-                printf("%d: %f %f\n", i, out[i].r, out[i].i);
+                printf("%d: %f %f\n", i, *(float*)&out[i].r, *(float*)&out[i].i);
             printf("----\n");
         }
         
@@ -59,7 +67,7 @@
 
         if (j == 0) {
             for (i = 0; i < 8; i++)
-                printf("%d: %f\n", i, res[i] / N);
+                printf("%d: %f\n", i, *(float*)&res[i] / N);
         }
     }
     peck_fftr_free(p);    
@@ -67,7 +75,7 @@
     peck_fft_cleanup();
 
     for (i = 0; i < N; i++) {
-        if (fabs(in[i] - res[i]/N) > 0.00001) {
+        if (fabs(*(float*)&in[i] - *(float*)&res[i]/N) > 0.00001) {
             fprintf(stderr, "!!!! ERROR !!!! at %d\n", i);
             exit(EXIT_FAILURE);
         }

Repositories maintained by Peter Meerwald, pmeerw@pmeerw.net.