我想知道诸如加法和乘法之类的 SSE/AVX 操作是否可以是原子操作?我问这个的原因是,在 OpenMP 中,原子构造仅适用于有限的一组运算符。它不适用于例如 SSE/AVX 添加。
假设我有一个float4
对应于 SSE 寄存器的数据类型,并且为 float4 定义了加法运算符以进行 SSE 加法。在 OpenMP 中,我可以使用以下代码对数组进行归约:
float4 sum4 = 0.0f; //sets all four values to zero
#pragma omp parallel
{
float4 sum_private = 0.0f;
#pragma omp for nowait
for(int i=0; i<N; i+=4) {
float4 val = float4().load(&array[i]) //load four floats into a SSE register
sum_private4 += val; //sum_private4 = _mm_addps(val,sum_private4)
}
#pragma omp critical
sum4 += sum_private;
}
float sum = horizontal_sum(sum4); //sum4[0] + sum4[1] + sum4[2] + sum4[3]
但是一般来说,原子比关键要快,我的直觉告诉我 SSE/AVX 操作应该是原子的(即使 OpenMP 不支持它)。这是 OpenMP 的限制吗?我可以使用例如英特尔线程构建块或 pthreads 来将其作为原子操作来执行吗?
编辑:根据 Jim Cownie 的评论,我创建了一个新功能,这是最好的解决方案。我验证它给出了正确的结果。
float sum = 0.0f;
#pragma omp parallel reduction(+:sum)
{
Vec4f sum4 = 0.0f;
#pragma omp for nowait
for(int i=0; i<N; i+=4) {
Vec4f val = Vec4f().load(&A[i]); //load four floats into a SSE register
sum4 += val; //sum4 = _mm_addps(val,sum4)
}
sum += horizontal_add(sum4);
}
编辑:基于评论 Jim Cownie 和 Mystical 在此线程 OpenMP atomic _mm_add_pd上的评论,我现在意识到 OpenMP 中的归约实现不一定使用原子运算符,最好依靠 OpenMP 的归约实现而不是尝试使用原子操作。