OpenMP 和 17 个嵌套 For 循环
OpenMP and 17 Nested For-Loops
我有一个巨大的嵌套 for 循环,旨在将一个大数组设置为其默认值。我第一次尝试使用 OpenMP 进行并行化,但不知道从哪里开始。我一直在阅读教程,担心该过程将在 N 个核心上独立执行,而不是 N 个核心将过程划分为共同输出。代码在 C 中,在 Visual Studio v14 中编译。感谢对这个新手的任何帮助——谢谢!
(下面附上嵌套for循环的怪物...)
for (j = 0;j < box1; j++)
{
for (k = 0; k < box2; k++)
{
for (l = 0; l < box3; l++)
{
for (m = 0; m < box4; m++)
{
for (x = 0;x < box5; x++)
{
for (y = 0; y < box6; y++)
{
for (xa = 0;xa < box7; xa++)
{
for (xb = 0; xb < box8; xb++)
{
for (nb = 0; nb < memvara; nb++)
{
for (na = 0; na < memvarb; na++)
{
for (nx = 0; nx < memvarc; nx++)
{
for (nx1 = 0; nx1 < memvard; nx1++)
{
for (naa = 0; naa < adirect; naa++)
{
for (nbb = 0; nbb < tdirect; nbb++)
{
for (ncc = 0; ncc < fs; ncc++)
{
for (ndd = 0; ndd < bs; ndd++)
{
for (o = 0; o < outputnum; o++)
{
lookup->n[j][k][l][m][x][y][xa][xb][nb][na][nx][nx1][naa][nbb][ncc][ndd][o] = -3; //set to default value
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
如果n
实际上是一个多维数组,可以这样做:
size_t i;
size_t count = sizeof(lookup->n) / sizeof(int);
int *p = (int*)lookup->n;
for( i = 0; i < count; i++ )
{
p[i] = -3;
}
现在,并行化要容易得多。
在这里阅读更多关于为什么这有效的信息(也适用于 C):How do I use arrays in C++?
我相信,根据高等教育研究,解决方案可能是在嵌套循环的正上方添加 #pragma omp parallel for collapse(N)
。然而,这似乎只适用于 OpenMP v3.0,整个项目目前基于 Visual Studio(因此,OpenMP v2.0)...
这更像是一个扩展评论,而不是一个答案。
求迭代极限(即box1
、box2
、等中的变量)的最大值。修改你的循环嵌套,使最外层的循环 运行 覆盖它。简单地并行化最外层的循环。选择最大值意味着您将在极限内为每个线程获得与 运行 相等的内循环迭代次数。
折叠循环,无论您可以使用 OpenMP 的 collapse
子句还是必须手动执行,仅当您有理由相信仅在最外层循环上并行化会导致严重的负载不平衡时才有用。在这种情况下,这似乎不太可能,因此在最外层的可用线程中(大约)平均分配工作可能会提供相当好的负载平衡。
我有一个巨大的嵌套 for 循环,旨在将一个大数组设置为其默认值。我第一次尝试使用 OpenMP 进行并行化,但不知道从哪里开始。我一直在阅读教程,担心该过程将在 N 个核心上独立执行,而不是 N 个核心将过程划分为共同输出。代码在 C 中,在 Visual Studio v14 中编译。感谢对这个新手的任何帮助——谢谢! (下面附上嵌套for循环的怪物...)
for (j = 0;j < box1; j++)
{
for (k = 0; k < box2; k++)
{
for (l = 0; l < box3; l++)
{
for (m = 0; m < box4; m++)
{
for (x = 0;x < box5; x++)
{
for (y = 0; y < box6; y++)
{
for (xa = 0;xa < box7; xa++)
{
for (xb = 0; xb < box8; xb++)
{
for (nb = 0; nb < memvara; nb++)
{
for (na = 0; na < memvarb; na++)
{
for (nx = 0; nx < memvarc; nx++)
{
for (nx1 = 0; nx1 < memvard; nx1++)
{
for (naa = 0; naa < adirect; naa++)
{
for (nbb = 0; nbb < tdirect; nbb++)
{
for (ncc = 0; ncc < fs; ncc++)
{
for (ndd = 0; ndd < bs; ndd++)
{
for (o = 0; o < outputnum; o++)
{
lookup->n[j][k][l][m][x][y][xa][xb][nb][na][nx][nx1][naa][nbb][ncc][ndd][o] = -3; //set to default value
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
如果n
实际上是一个多维数组,可以这样做:
size_t i;
size_t count = sizeof(lookup->n) / sizeof(int);
int *p = (int*)lookup->n;
for( i = 0; i < count; i++ )
{
p[i] = -3;
}
现在,并行化要容易得多。
在这里阅读更多关于为什么这有效的信息(也适用于 C):How do I use arrays in C++?
我相信,根据高等教育研究,解决方案可能是在嵌套循环的正上方添加 #pragma omp parallel for collapse(N)
。然而,这似乎只适用于 OpenMP v3.0,整个项目目前基于 Visual Studio(因此,OpenMP v2.0)...
这更像是一个扩展评论,而不是一个答案。
求迭代极限(即box1
、box2
、等中的变量)的最大值。修改你的循环嵌套,使最外层的循环 运行 覆盖它。简单地并行化最外层的循环。选择最大值意味着您将在极限内为每个线程获得与 运行 相等的内循环迭代次数。
折叠循环,无论您可以使用 OpenMP 的 collapse
子句还是必须手动执行,仅当您有理由相信仅在最外层循环上并行化会导致严重的负载不平衡时才有用。在这种情况下,这似乎不太可能,因此在最外层的可用线程中(大约)平均分配工作可能会提供相当好的负载平衡。