gpt4 book ai didi

c++ - OpenMP 原子 _mm_add_pd

转载 作者:太空宇宙 更新时间:2023-11-03 10:32:05 28 4
gpt4 key购买 nike

我正在尝试使用 OpenMP 对已经矢量化的代码进行内部函数并行化,但问题是我使用一个 XMM 寄存器作为外部“变量”,我会在每个循环中递增。现在我正在使用 shared 子句

__m128d xmm0 = _mm_setzero_pd();
__declspec(align(16)) double res[2];

#pragma omp parallel for shared(xmm0)
for (int i = 0; i < len; i++)
{
__m128d xmm7 = ... result of some operations

xmm0 = _mm_add_pd(xmm0, xmm7);
}

_mm_store_pd(res, xmm0);
double final_result = res[0] + res[1];

因为不支持atomic操作(在VS2010中)

__m128d xmm0 = _mm_setzero_pd();
__declspec(align(16)) double res[2];

#pragma omp parallel for
for (int i = 0; i < len; i++)
{
__m128d xmm7 = ... result of some operations

#pragma omp atomic
xmm0 = _mm_add_pd(xmm0, xmm7);
}

_mm_store_pd(res, xmm0);
double final_result = res[0] + res[1];

有谁知道一个巧妙的解决方法?


编辑:我刚才也使用并行模式库尝试过:

__declspec(align(16)) double res[2];
combinable<__m128d> xmm0_comb([](){return _mm_setzero_pd();});

parallel_for(0, len, 1, [&xmm0_comb, ...](int i)
{
__m128d xmm7 = ... result of some operations

__m128d& xmm0 = xmm0_comb.local();
xmm0 = _mm_add_pd(xmm0, xmm7);
});

__m128d xmm0 = xmm0_comb.combine([](__m128d a, __m128d b){return _mm_add_pd(a, b);});
_mm_store_pd(res, xmm0);
double final_result = res[0] + res[1];

但结果却令人失望。

最佳答案

您正在以错误的方式解决问题。您应该使用归约而不是原子操作:

这是一个更好的方法:

double sum = 0;

#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < len; i++)
{
__m128d xmm7;// = ... result of some operations

// Collapse to a "double".
_declspec(align(16)) double res[2];
_mm_store_pd(res, xmm7);

// Add to reduction variable.
sum += res[0] + res[1];
}

double final_result = sum;

缩减本质上是一种操作,它使用 + 等关联操作将所有内容“缩减”为单个变量。

如果您要进行缩减,请始终尝试使用实际的缩减方法。不要试图用原子操作或关键部分来欺骗它。

这样做的原因是原子/关键部分方法本质上是不可扩展的,因为它们保持了长期的关键路径数据依赖性。适当的缩减方法将这条关键路径缩减为 log(# of threads)

当然,唯一的缺点是它破坏了浮点关联性。如果这很重要,那么您基本上只能按顺序总结每次迭代。

关于c++ - OpenMP 原子 _mm_add_pd,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14014874/

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