For loop 平行';任务';在已经并行化的';对于';OpenMP中的循环
[背景:英特尔icc编译器上的OpenMP v4+] 我想在已经并行化的循环中并行化任务。我看到了很多关于这个主题的问题,例如:For loop 平行';任务';在已经并行化的';对于';OpenMP中的循环,for-loop,parallel-processing,task,openmp,For Loop,Parallel Processing,Task,Openmp,[背景:英特尔icc编译器上的OpenMP v4+] 我想在已经并行化的循环中并行化任务。我看到了很多关于这个主题的问题,例如: 还有更集中的智慧 但在尝试时,除了编译时的错误消息外,我无法得到明确的答案 代码: #pragma omp并行用于私有(a,bd)缩减(+:sum) 对于(int i=0;i循环工作共享构造中的单个工作共享构造是标准所禁止的,但您不需要它 通常的并行->单个->任务设置是为了确保您的任务有一个线程组设置(并行),但每个任务只生成一次(单个)。对于上下文,您不需
- 还有更集中的智慧
#pragma omp并行用于私有(a,bd)缩减(+:sum)
对于(int i=0;i循环工作共享构造中的单个工作共享构造是标准所禁止的,但您不需要它
通常的并行
->单个
->任务
设置是为了确保您的任务有一个线程组设置(并行
),但每个任务只生成一次(单个
)。对于
上下文,您不需要在并行中使用后者,因为每个迭代只执行一次。因此,您可以直接在循环中生成任务。这似乎在gnu和英特尔编译器上都具有预期的行为,即已完成自己循环迭代的线程确实帮助其他线程执行其tasks
但是,在您的情况下,这是一个坏主意。与生成任务的开销相比,一个微小的计算,例如sum1
本身会快得多
删除除的并行之外的所有pragma,这是一种非常合理的并行化。在进一步优化计算之前,您应该测量!特别是,您感兴趣的是,是否所有可用线程都在计算某个内容,或者某些线程是否提前完成并等待其他内容rs(负载不平衡)。要测量,您应该为您的平台寻找一个并行性能分析工具。如果是这种情况,您可以使用调度策略,或者可能通过内部循环中的嵌套并行来解决
对代码性能的全面讨论要复杂得多,需要详细的系统描述和实际测量的性能数字。谢谢Zulan。你的解释肯定比编译时错误信息要好。根据你的指示,我将查看集群上的测量仪器。干杯,
#pragma omp parallel for private(a,bd) reduction(+:sum)
for (int i=0; i<128; i++) {
a = i%2;
for (int j=a; j<128; j=j+2) {
u_n = 0.25 * ( u[ i*128 + (j-3) ]+
u[ i*128 + (j+3) ]+
u[ (i-1)*128 + j ]+
u[ (i+1)*128 + j ]);
// #pragma omp single nowait
// {
// #pragma omp task shared(sum1) firstprivate(i,j)
// sum1 = (u[i*128+(j-3)]+u[i*128+(j-2)] + u[i*128+(j-1)])/3;
// #pragma omp task shared(sum2) firstprivate(i,j)
// sum2 = (u[i*128+(j+3)]+u[i*128+(j+2)]+u[i*128+(j+1)])/3;
// #pragma omp task shared(sum3) firstprivate(i,j)
// sum3 = (u[(i-1)*128+j]+u[(i-2)*128+j]+u[(i-3)*128+j])/3;
// #pragma omp task shared(sum4) firstprivate(i,j)
// sum4 = (u[(i+1)*128+j]+u[(i+2)*128+j]+u[(i+3)*128+j])/3;
// }
// #pragma omp taskwait
// {
// u_n = 0.25*(sum1+sum2+sum3+sum4);
// }
bd = u_n - u[i*128+ j];
sum += diff * diff;
u[i*128+j]=u_n;
}
}