OpenMP 实现的归约

Rom*_*kyi 0 c openmp

我需要实现归约操作(对于每个线程,值应该存储在不同的数组条目中)。但是,对于更多线程,它运行得更慢。有什么建议?

double local_sum[16];.
//Initializations....
#pragma omp parallel for shared(h,n,a) private(x, thread_id) 
for (i = 1; i < n; i++) {
    thread_id = omp_get_thread_num();
    x = a  + i* h;
    local_sum[thread_id] += f(x);
}
Run Code Online (Sandbox Code Playgroud)

Hri*_*iev 5

您正在体验虚假共享的影响。在 x86 上,单个缓存行的长度为 64 字节,因此包含64 / sizeof(double)= 8 个数组元素。当一个线程更新其元素时,它运行的核心使用缓存一致性协议使所有其他核心中的相同缓存行无效。当另一个线程更新它的元素,而不是直接在缓存上操作时,它的核心必须从上层数据缓存或主内存中重新加载缓存行。这会显着减慢程序的执行速度。

最简单的解决方案是插入填充,从而将不同线程访问的数组元素分散到不同的缓存行中。在 x86 上,这将是 7 个double元素。因此,您的代码应如下所示:

double local_sum[8*16];
//Initializations....
#pragma omp parallel for shared(h,n,a) private(x, thread_id) 
for (i = 1; i < n; i++) {
    thread_id = omp_get_thread_num();
    x = a  + i* h;
    local_sum[8*thread_id] += f(x);
Run Code Online (Sandbox Code Playgroud)

}

在最后对数组求和时不要忘记只取第 8 个元素(或将所有数组元素初始化为零)。