我需要实现还原操作(对于每个线程,值应该存储在不同的数组条目中)。但是,对于更多线程,它运行速度较慢。有什么建议吗?
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);
}
答案 0 :(得分:4)
您正在体验虚假分享的影响。在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);
}
在最后对数组进行求和(或将所有数组元素初始化为零)时,不要忘记仅取每个第8个元素。
答案 1 :(得分:-2)
您是否尝试使用还原?
double global_sum = 0.0;
#pragma omp parallel for shared(h,n,a) reduction(+:global_sum)
for (i = 1; i < n; i++) {
global_sum += f(a + i* h);
}
然而,为什么它运行缓慢可能有很多其他原因。例如,如果只有2个CPU核心,则不应创建16个线程。