#include #include #include #include #include #include #include "vec1.c" #ifdef VEC1_HAVE_NEON /* ** Run nIter iterations of a loop containing N independent, back-to-back ** FMA chains (N float32x4_t accumulators, each updated once per ** iteration) and return the elapsed time on vec1HardwareTimer(). ** ** N is a literal compile-time constant at every call site (see ** MAKE_FMA_TEST below), so the "for(c...)" loop below is unrolled by ** the compiler into straight-line code - there is no loop-control ** instruction diluting the measurement, and for N==1 this is a single ** dependent chain (true FMA latency); for larger N it is N independent ** chains (FMA throughput, once N is large enough to hide the latency). */ #define MAKE_FMA_TEST(N) \ static u64 vec1FmaTest##N(int nIter){ \ float32x4_t acc[N]; \ float32x4_t a = vdupq_n_f32(1.000001f); \ float32x4_t b = vdupq_n_f32(0.999999f); \ int c, r; \ u64 t; \ for(c=0; cbestRate ) bestRate = fmaPerTick; } nOptimal = (int)ceil(latency * bestRate); printf("\n"); printf("FMA latency (N=1, dependent chain): %.3f ticks\n", latency); printf("FMA throughput (best of N tested): %.3f FMA/tick\n", bestRate); printf("Little's Law: accumulators needed = latency * throughput\n"); printf(" = %.3f * %.3f = %.2f -> use %d independent accumulators\n", latency, bestRate, latency*bestRate, nOptimal); } #endif /* VEC1_HAVE_NEON */ /* ** Populate aTrans[] with transposed version of the array of centroids in ** aCentroid[]. */ static void vec1TransposeCentroids( const float *aCentroid, /* Packed array of centroids */ int nElem, /* Number of elements in each vector */ int nVector, /* Number of centroid vectors */ int nWidth, /* Transpose width */ float *aTrans /* Populate this array with transformation */ ){ int c, d; float *pOut = aTrans; /* nVector must be an integer multiple of nWidth */ assert( (nVector % nWidth)==0 ); for(c=0; c> 8) * (1.0 / 16777216.0); // 24-bit mantissa } static void vec1RandomArray(Vec1Random *p, float *aRnd, int nRnd){ int ii; for(ii=0; iifBest && (fDist-fBest)/fDist>fTol) || (fDistfTol) ){ fprintf(stderr, "algorithm FAILED...\n"); return 1; } } } #endif printf("Cycles: "); if( t>(1000*1000*1000) ){ printf("%.2fG\n", (double)t / 1000000000.0); }else if( t>(10*1000*1000) ){ printf("%dM\n", (int)(t / (1000*1000))); }else if( t>(1*1000*1000) ){ printf("%.2fM\n", (double)t / (1000*1000)); }else{ printf("%d\n", (int)t); } return 0; }