Openmp-嵌套用于循环

Openmp - Nested for-loop

本文关键字:循环 用于 嵌套 Openmp-      更新时间:2023-10-16

如何安全地线程化下面的嵌套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.;
}
}
}
}

不能以这种方式嵌套OMP区域。来自OMP文档(英特尔):

两个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上也提出过类似的问题并得到了回答。

OpenMP,用于内部环路

用于具有主区域的循环的OpenMP:";主区域可以不紧密地嵌套在工作共享或显式任务区域内;