[后台:英特尔icc编译器上的OpenMP v4 +]
我想在已经并行化的循环中并行化任务。我看到了很多关于这个主题的问题,例如:
但是在尝试时我无法获得除编译时错误消息之外的明确答案。
代码:
#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;
}
}
在上面的代码中,我尝试用15条注释行替换u_n = 0.25 *(...);
行,不仅尝试对2 for
个循环的迭代进行并行化,而且还尝试实现一定程度的并行性涉及数组sum1
的4个计算(sum4
到u[]
)中的每个计算。
编译错误非常明确:
错误:OpenMP&#34;单&#34; pragma不得被包围 &#34;平行于&#34;附注
有没有解决方法,所以我可以使用OpenMP进一步优化计算?
答案 0 :(得分:1)
标准禁止循环工作共享构造中的单个工作共享构造,但您不需要它。
通常parallel
- &gt; single
- &gt; task
任务设置是为了确保您为任务(parallel
)设置了一个线程团队,但是只生成一次任务(single
)。您不需要在parallel for
上下文中使用后者,因为每次迭代只执行一次。所以你可以直接在循环中生成任务。这似乎在gnu和Intel编译器上都有预期的行为,即已经完成自己的循环迭代的线程确实帮助其他线程执行他们的任务。
但是,在您的情况下,这是一个坏主意。与产生任务的开销相比,像sum1
那样的微小计算会比它自己快得多。
删除除parallel for
之外的所有编译指示,这是一个非常合理的并行化。在进一步优化计算之前,您应该衡量!特别是,您感兴趣的是所有可用线程是否总是在计算某些东西,或者某些线程是否提前完成并等待其他线程(负载不平衡)。要进行衡量,您应该为您的平台寻找并行性能分析工具。如果是这种情况,您可以使用调度策略或内部循环中的嵌套并行性来解决它。
对代码性能的完整讨论更复杂,需要minimal, complete and verifiable example,详细的系统描述和实际测量的性能数字。