我正在尝试使用SIMD指令来加速我的C代码中的点积计算。然而,我的函数运行时间大致相等。如果有人可以解释为什么以及如何加速计算,那就太好了。
具体来说,我正在尝试计算两个数组的点积,每个数组中大约有10,000个元素。我的常规C函数如下:
我认为my_sum_m256操作可以更高效,但我认为这只会对运行时间产生很小的影响。我本来以为SIMD代码速度会快8倍左右。你们有什么想法吗?
感谢大家的帮助 :)
具体来说,我正在尝试计算两个数组的点积,每个数组中大约有10,000个元素。我的常规C函数如下:
float my_dotProd( float const * const x, float const * const y, size_t const N ){
// N is the number of elements in the arrays
size_t i;
float out=0;
for( i=0; i < N; ++i ){
out += x[i] * y[i];
}
return out;
}
我使用 AVX SIMD 指令的函数如下:
void my_malloc( size_t nBytes, void ** ptrPtr ){
int boundary = 32;
posix_memalign( ptrPtr, boundary, nBytes );
}
float cimpl_sum_m128( __m128 x ){
float out;
__m128 sum = x;
sum = _mm_hadd_ps( sum, sum );
sum = _mm_hadd_ps( sum, sum );
out = _mm_cvtss_f32( sum );
return out;
}
float my_sum_m256( __m256 x ){
float out1, out2;
__m128 hi = _mm256_extractf128_ps(x, 1);
__m128 lo = _mm256_extractf128_ps(x, 0);
out1 = cimpl_sum_m128( hi );
out2 = cimpl_sum_m128( lo );
return out1 + out2;
}
float my_dotProd( float const * const x, float const * const y, size_t const N ){
// N is the number of elements in the arrays
size_t i=0;
float out=0;
float *tmp;
__m256 summed, *l, *r;
if( N > 7 ){
my_malloc( sizeof(float) * 8, (void**) &tmp );
summed = _mm256_set1_ps(0.0f);
l = (__m256*) x;
r = (__m256*) y;
for( i=0; i < N-7; i+=8, ++l, ++r ){
summed = _mm256_add_ps( summed, _mm256_mul_ps( *l, *r ) );
}
_mm256_store_ps( tmp, summed );
out += my_sum_m256( summed );
free( tmp );
}
for( ; i < N; ++i ){
out += x[i] * y[i];
}
return out;
}
我的测试程序如下:
int test_dotProd(){
float *x, *y;
size_t i, N;
float answer, result;
float err;
N = 100000; // Fails
my_malloc( sizeof(float) * N, (void**) &x );
my_malloc( sizeof(float) * N, (void**) &y );
answer = 0;
for( i=0; i<N; ++i ){
x[i]=i; y[i]=i;
answer += (float)i * (float)i;
}
result = my_dotProd( x, y, N );
err = fabs( result - answer ) / answer;
free( x );
free( y );
return err < 5e-7;
}
我正在使用时钟来测量运行时间,如下所示:
timeStart = clock();
testStatus = test_dotProd();
timeTaken = (int)( clock() - timeStart );
我认为my_sum_m256操作可以更高效,但我认为这只会对运行时间产生很小的影响。我本来以为SIMD代码速度会快8倍左右。你们有什么想法吗?
感谢大家的帮助 :)
malloc
来分配tmp是没有意义的。这样做比直接使用栈要慢得多。 - Sami Kuhmonen