gpt4 book ai didi

c - 如何使用 SSE2 添加数组中的所有元素?

转载 作者:行者123 更新时间:2023-12-05 01:19:55 24 4
gpt4 key购买 nike

假设我有一个非常简单的代码,例如:

double array[SIZE_OF_ARRAY];
double sum = 0.0;

for (int i = 0; i < SIZE_OF_ARRAY; ++i)
{
sum += array[i];
}

我基本上想使用 SSE2 进行相同的操作。我怎样才能做到这一点?

最佳答案

这是一个非常简单的 SSE3 实现:

#include <emmintrin.h>

__m128d vsum = _mm_set1_pd(0.0);
for (int i = 0; i < n; i += 2)
{
__m128d v = _mm_load_pd(&a[i]);
vsum = _mm_add_pd(vsum, v);
}
vsum = _mm_hadd_pd(vsum, vsum);
double sum = _mm_cvtsd_f64(vsum0);

您可以通过使用多个累加器来隐藏 FP 添加的延迟(如@Mysticial 所建议的)来展开循环以获得更好的性能。使用多个“和” vector 展开 3 或 4 次,以达到负载和 FP-add 吞吐量(每个时钟周期一或两个)的瓶颈,而不是 FP-add 延迟(每 3 或 4 个周期一个):
__m128d vsum0 = _mm_setzero_pd();
__m128d vsum1 = _mm_setzero_pd();
for (int i = 0; i < n; i += 4)
{
__m128d v0 = _mm_load_pd(&a[i]);
__m128d v1 = _mm_load_pd(&a[i + 2]);
vsum0 = _mm_add_pd(vsum0, v0);
vsum1 = _mm_add_pd(vsum1, v1);
}
vsum0 = _mm_add_pd(vsum0, vsum1); // vertical ops down to one accumulator
vsum0 = _mm_hadd_pd(vsum0, vsum0); // horizontal add of the single register
double sum = _mm_cvtsd_f64(vsum0);

注意数组 a假定为 16 字节对齐且元素数量 n假定为 2(或 4,在展开循环的情况下)的倍数。

另见 Fastest way to do horizontal float vector sum on x86用于在循环外进行水平求和的替代方法。 SSE3 支持并不完全通用(尤其是 AMD CPU 比 Intel 更晚支持它)。

另外, _mm_hadd_pd即使在支持它的 CPU 上,通常也不是最快的方式,因此仅 SSE2 版本在现代 CPU 上不会更糟。但是,它在循环之外,并且两种方式都没有太大区别。

关于c - 如何使用 SSE2 添加数组中的所有元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12680668/

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