使用SSE / AVX的整数点积?

时间:2014-04-20 18:53:09

标签: c++ vectorization sse simd avx

我正在查看英特尔内在指南:

https://software.intel.com/sites/landingpage/IntrinsicsGuide/

虽然他们有_mm_dp_ps_mm_dp_pd来计算浮点数和双打的点积,但是我看不到任何用于计算整数点积的东西。

我有两个unsigned int[8]数组,我想:

(a [0] xb [0])+(a [1] * b [1])....... +(a [num_elements_in_array-1] * b [num_elements_in_array-1])

(分四批)并总结产品?

1 个答案:

答案 0 :(得分:12)

每次有人这样做:

temp_1 = _mm_set_epi32(x[j], x[j+1], x[j+2], x[j+3]);

..一只小狗死了。

使用以下其中一项:

temp_1 = _mm_load_si128(x);  // if aligned
temp_1 = _mm_loadu_si128(x); // if not aligned

根据需要投放x

_mm_dp_ps没有整数版本。但你可以做你将要做的事情:乘以4乘4整数,积累产品的总和。

所以像这样(没有经过测试,不能编译)

while(j < num_elements_in_array){
    //Load the 4 values from x
    temp_1 = _mm_load_si128(x + j); // add cast
    //Load the 4 values from y
    temp_2 = _mm_load_si128(y + j); // add cast
    j += 4;
    //Multiply x[0] and y[0], x[1] and y[1] etc
    temp_products = _mm_mullo_epi32(temp_1, temp_2);
    //Sum temp_sum
    temp_sum = _mm_add_epi32(temp_sum, temp_products);
}
// take horizontal sum of temp_sum
temp_sum = _mm_add_epi32(temp_sum, _mm_srli_si128(temp_sum, 8));
temp_sum= _mm_add_epi32(temp_sum, _mm_srli_si128(temp_sum, 4));
sum = _mm_cvtsi128_si32(temp_sum);

正如评论和聊天中所讨论的那样,重新排序总和的方式是最大限度地减少所需的水平总和数量,通过垂直方式进行大多数求和。