SIMD/SSE:短点积和短最大值
SIMD/SSE : short dot product and short max value
我正在尝试优化两个c样式数组的点积,这两个数组的大小都很小,类型也很短。
我已经阅读了一些关于SIMD本质的文档,以及许多关于使用这个本质优化点产品的博客文章。
然而,我不明白使用这种内部函数的短数组上的点积如何能给出正确的结果。在制作点积时,计算出的值可以(在我的情况下总是)大于SHORT_MAX,所以有和。因此,我将它们存储在double类型的变量中。
正如我所理解的使用simd内在的点积,我们使用__m128i变量类型,运算返回__m128i。所以,我不明白的是,为什么它不"溢出",以及如何将结果转换为可以处理它的值类型?
感谢您的建议
根据数据值的范围,您可以使用诸如_mm_madd_epi16之类的内部函数,该函数对16位数据执行乘法/加法运算,并生成32位项。然后,您需要周期性地将32位项累积为64位。你需要多久做一次取决于你的输入数据的范围,例如,如果它是12位灰度图像数据,那么在存在溢出的可能性之前,你可以在每次迭代8个元素(即512个输入点)的情况下进行64次迭代。然而,在最坏的情况下,如果您的输入数据使用完整的16位范围,那么您需要在每次迭代(即每8点)中进行额外的64位累加。
仅就记录而言,以下是我如何为2个36大小的int16数组制作点积:
double dotprod(const int16_t* source, const int16_t* target, const int size){
#ifdef USE_SSE
int res[4];
__m128i* src = (__m128i *) source;
__m128i* t = (__m128i *) target;
__m128i s = _mm_madd_epi16(_mm_loadu_si128(src), mm_loadu_si128(t));
++src;
++t;
s = _mm_add_epi32(s, _mm_madd_epi16(_mm_loadu_si128(src), _mm_loadu_si128(t)));
++src;
++t;
s = _mm_add_epi32(s, _mm_madd_epi16(_mm_loadu_si128(src), _mm_loadu_si128(t)));
++src;
++t;
s = _mm_add_epi32(s, _mm_madd_epi16(_mm_loadu_si128(src), _mm_loadu_si128(t)));
/* return the sum of the four 32-bit sub sums */
_mm_storeu_si128((__m128i*)&res, s);
return res[0] + res[1] + res[2] + res[3] + source[32] * target[32] + source[33] * target[33] + source[34] * target[34] + source[35] * target[35];
#elif USE_AVX
int res[8];
__m256i* src = (__m256i *) source;
__m256i* t = (__m256i *) target;
__m256i s = _mm256_madd_epi16(_mm256_loadu_si256(src), _mm256_loadu_si256(t));
++src;
++t;
s = _mm256_add_epi32(s, _mm256_madd_epi16(_mm256_loadu_si256(src), _mm256_loadu_si256(t)));
/* return the sum of the 8 32-bit sub sums */
_mm256_storeu_si256((__m256i*)&res, s);
return res[0] + res[1] + res[2] + res[3] + res[4] + res[5] + res[6] + res[7] + source[32] * target[32] + source[33] * target[33] + source[34] * target[34] + source[35] * target[35];
#else
return source[0] * target[0] + source[1] * target[1] + source[2] * target[2] + source[3] * target[3] + source[4] * target[4]+ source[5] * target[5] + source[6] * target[6] + source[7] * target[7] + source[8] * target[8] + source[9] * target[9] + source[10] * target[10] + source[11] * target[11] + source[12] * target[12] + source[13] * target[13] + source[14] * target[14] + source[15] * target[15] + source[16] * target[16] + source[17] * target[17] + source[18] * target[18] + source[19] * target[19] + source[20] * target[20] + source[21] * target[21] + source[22] * target[22] + source[23] * target[23] + source[24] * target[24] + source[25] * target[25] + source[26] * target[26] + source[27] * target[27] + source[28] * target[28] + source[29] * target[29] + source[30] * target[30] + source[31] * target[31] + source[32] * target[32] + source[33] * target[33] + source[34] * target[34] + source[35] * target[35];
#endif
}
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 使用指针从C++中的数组中获取最大值
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 如何创建一个函数来计算并返回平均值、最大值和最小值
- 在二维数组中查找最小值和最大值?
- 整数溢出,最大值为 pow(10,19)
- 以C++递归方式查找向量中的最大值
- C++ - 如何在结构向量中找到结构体一个成员的最大值?
- 查找数组中第一个最小值和最后一个最大值元素之间的算术平均值
- C++ 函数,用于查找传入的 N 个数字的平均值、总和、最小值和最大值
- 我的 If Else 语句无法在向量 (C++) 中提供最大值
- 如何使用可变参数模板类使用模板元编程获得最大值
- C++不同的最小最大值实现
- Vec3b:r/g/b 颜色的最大值为 254,而不是 255
- CUDA - 将 float3 数组的 (x,y,z) 分量的最小值/最大值分开?
- 是否可以将无符号 int 的最大值转换为 int 并将结果转换为 -1?
- 查找包含 N 个元素的数组的最小值和最大值
- 井字游戏具有奇怪行为的最小最大值算法(C++)
- 错误C++在Visual Studio 2019中使用numeric_limits的长双精度最小值/最大值
- SIMD/SSE:短点积和短最大值