并行“任务的内线已经并行for循环OpenMP中
背景:OpenMP的V4 +英特尔的编译器ICC]并行“任务的内线已经并行for循环OpenMP中
我想并行化已经是一个并行循环内的任务。我看见科目接近这一个,例如:
- Parallel sections in OpenMP using a loop
- Doing a section with one thread and a for-loop with multiple threads
- 和others更集中智慧,还有不少疑问。
但是在尝试它时,除了编译时错误消息,我无法得到明确的答案。
代码:
#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;
}
}
在上面的代码中,我试图替换u_n = 0.25 *(...);
符合15注释行,不仅尝试通过2个for
循环来paralllelize迭代,而且还acheive一定程度在涉及数组u[]
的4次计算(sum1
到sum4
)中的每一次计算上都是并行性的。
编译错误是相当明确的:
error: the OpenMP "single" pragma must not be enclosed by the "parallel for" pragma
有没有解决的办法,所以我可以进一步优化该计算使用OpenMP?
标准禁止在循环工作共享结构中的单个工作共享构造,但您不需要它。
通常parallel
- >single
- >task
设置的任务是要确保你有一个线程组设置为您的任务(parallel
),但后来只产卵每个任务一次(single
)。你不需要parallel for
上下文中的后者,因为每次迭代只能执行一次。所以你可以直接在循环中产生任务。这似乎在gnu和Intel编译器上都有预期的行为,即已完成自己的循环迭代的线程确实帮助其他线程执行其任务。
但是,在你的情况下这是一个坏主意。与产卵任务的开销相比,像sum1
之类的微小计算本身会更快。
删除除parallel for
以外的所有编译指示,这是非常合理的并行化。 之前进一步优化计算,你应该措施!尤其是,您对所有可用线程是否总是在计算某些内容感兴趣,或者某些线程是否提前完成并等待其他线程(负载不均衡)。要衡量,您应该为您的平台寻找并行性能分析工具。如果是这样的话,你可以用调度策略来解决它,或者可能通过内部循环中的嵌套并行。
关于代码性能的完整讨论比较复杂,需要一个minimal, complete and verifiable example,详细的系统描述和实际测量的性能数字。
谢谢佐兰。Yr解释肯定会击败编译时错误信息。根据你的指针,我将在我的集群上查看测量仪器。干杯, – Cbhihe