如何安全地在下面安装嵌套的for循环,以便在具有8个线程的核心上并行运行程序,并仍以正确的顺序输出数据。我尝试使用 #pragma omp for 命令,但这会给我一条错误消息: 工作共享区域可能没有紧密嵌套在工作中 - 共享,关键或显式任务区域 。
注意:此代码用于介绍并行编程,因此为了优化而编写的代码很差
#pragma omp parallel private(t, i, j) shared(nx, ny, nt)
{
// main loop
for (int t = 0; t < nt; t++)
{
cout << "\n" << t;
cout.flush();
// first block
for (int i = 0; i < nx; i++)
{
for(int j=0; j < ny ;j++)
{
if (i> 0 && i < nx - 1 && j >0 && j < ny - 1)
{
vr[i][j] = (vi[i+1][j]+vi[i-1][j]+vi[i][j-1]+vi[i][j+1]) / 4.;
}
else if (i == 0 && i < nx - 1 && j > 0 && j < ny - 1)
{
vr[i][j] = (vi[i+1][j]+10.+vi[i][j-1]+vi[i][j+1]) / 4.;
}
else if (i > 0 && i == nx - 1 && j > 0 && j < ny - 1)
{
vr[i][j] = (5.+vi[i-1][j]+vi[i][j-1]+vi[i][j+1]) / 4.;
}
else if (i > 0 && i < nx - 1 && j == 0 && j < ny - 1)
{
vr[i][j] = (vi[i+1][j]+vi[i-1][j]+15.45+vi[i][j+1]) / 4.;
}
else if (i > 0 && i < nx - 1 && j > 0 && j == ny - 1)
{
vr[i][j] = (vi[i+1][j]+vi[i-1][j]+vi[i][j-1]-6.7) / 4.;
}
}
}
// second block
for (int i = 0; i < nx; i++)
{
for (int j = 0; j < ny; j++)
{
if (fabs(fabs(vr[i][j]) - fabs(vi[i][j])) < 1e-2)
{
fout << "\n" << t << " " << i << " " << j << " "
<< fabs(vi[i][j]) << " " << fabs(vr[i][j]);
}
}
#pragma omp for schedule(static,100)
// third block
for (int i = 0; i < nx; i++)
{
for (int j = 0; j < ny; j++)
{
vi[i][j] = vi[i][j] / 2. + vr[i][j] / 2.;
}
}
}
}
答案 0 :(得分:2)
您无法以这种方式嵌套OMP区域。来自OMP documentation (Intel):
两个OpenMP构造是不正确(动态)嵌套的。 OpenMP规范对如何动态嵌套OpenMP构造施加了若干限制,也就是说,在执行另一个区域期间可以合法地遇到哪些OpenMP构造。 OpenMP并行区域可以相互嵌套,但有一些限制。 一般来说,如果存在由SINGLE,CRITICAL或MASTER指令创建的中间单线程区域,则只能嵌套两个并行区域。
准确地说,以下限制适用。在下文中,术语“工作共享区域”是以下任何一种构造的简写:循环(FOR / DO),SECTIONS,SINGLE或WORKSHARE。术语“紧密嵌套的区域”是指动态嵌套在另一个区域内的区域,它们之间没有嵌套的平行区域。
- 工作共享区域可能不会紧密嵌套在工作共享,显式TASK,CRITICAL,ORDERED或MASTER区域内。
- BARRIER区域可能不会紧密嵌套在工作共享,显式TASK,CRITICAL,ORDERED或MASTER区域内。
- MASTER区域可能不会紧密嵌套在工作共享或显式TASK区域内。
- ORDERED区域可能不会紧密嵌套在CRITICAL或显式TASK区域内。
- ORDERED区域必须使用ORDERED子句紧密嵌套在循环区域(或并行循环区域)内。
- CRITICAL区域不能嵌套(密切地或以其他方式)在具有相同名称的CRITICAL区域内(尽管违反此限制的报告的错误类型与此不同)。
之前在SO上已经提出并回答了类似的问题。