gpt4 book ai didi

c - 如何在 C 语言中使用 SSE 内在函数计算单 vector 点积

转载 作者:太空狗 更新时间:2023-10-29 16:45:58 26 4
gpt4 key购买 nike

我正在尝试将两个 vector 相乘,其中一个 vector 的每个元素都乘以另一个 vector 中同一索引中的元素。然后我想对结果 vector 的所有元素求和以获得一个数字。例如, vector {1,2,3,4} 和 {5,6,7,8} 的计算如下所示:

1*5 + 2*6 + 3*7 + 4*8

本质上,我计算的是两个 vector 的点积。我知道有一个 SSE 命令可以执行此操作,但该命令没有与之关联的内在功能。此时,我不想在我的 C 代码中编写内联汇编,所以我只想使用内部函数。这似乎是一个常见的计算,所以我很惊讶自己无法在 Google 上找到答案。

注意:我正在针对最高支持 SSE 4.2 的特定微架构进行优化。

最佳答案

如果您要计算较长 vector 的点积,请使用乘法和正则 _mm_add_ps (或 FMA)在内循环中。保存水平和直到结束。


但是如果您只对一对 SIMD vector 进行点积:

GCC(至少版本 4.3)包括 <smmintrin.h>具有 SSE4.1 级内在函数,包括单精度和 double 点积:

_mm_dp_ps (__m128 __X, __m128 __Y, const int __M);
_mm_dp_pd (__m128d __X, __m128d __Y, const int __M);

在 Intel 主流 CPU(不是 Atom/Silvermont)上,这些比使用多条指令手动执行要快一些。

但在 AMD(包括 Ryzen)上,dpps明显较慢。 (参见 Agner Fog's instruction tables)


作为旧处理器的回退,您可以使用此算法创建 vector 的点积 ab :

__m128 r1 = _mm_mul_ps(a, b);

然后水平求和r1使用 Fastest way to do horizontal float vector sum on x86 (查看此处的评论版本,以及为什么它更快。)

__m128 shuf   = _mm_shuffle_ps(r1, r1, _MM_SHUFFLE(2, 3, 0, 1));
__m128 sums = _mm_add_ps(r1, shuf);
shuf = _mm_movehl_ps(shuf, sums);
sums = _mm_add_ss(sums, shuf);
float result = _mm_cvtss_f32(sums);

慢速替代方案每 hadd 花费 2 次洗牌,这很容易成为 shuffle 吞吐量的瓶颈,尤其是在 Intel CPU 上。

r2 = _mm_hadd_ps(r1, r1);
r3 = _mm_hadd_ps(r2, r2);
_mm_store_ss(&result, r3);

关于c - 如何在 C 语言中使用 SSE 内在函数计算单 vector 点积,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4120681/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com