我遇到了一个带有崩溃子句的OpenMP代码,这对我来说是新的。我试图理解它的含义,但是我认为我没有完全理解它的含义。我发现的一个定义是:
我以为我明白这意味着什么,所以尝试了以下简单程序:
int i, j;
#pragma omp parallel for num_threads(2) private(j)
for (i = 0; i < 4; i++)
for (j = 0; j <= i; j++)
printf("%d %d %d\n", i, j, omp_get_thread_num());
哪个产生
0 0 0
1 0 0
1 1 0
2 0 0
2 1 0
2 2 1
3 0 1
3 1 1
3 2 1
3 3 1
然后,我添加了
collapse(2)
子句。我希望在前两列中具有相同的结果,但在最后一列中具有相等数量的0
和1
。但是我得到了
0 0 0
1 0 0
2 0 1
3 0 1
所以我的问题是:
collapse
? collapse
与不使用ojit_code之间的区别? 最佳答案
您的代码的问题在于,内循环的迭代取决于外循环。根据有关绑定(bind)和collapse
子句的部分下的OpenMP规范:
如果不是这种情况,则可以使用折叠,例如使用方形循环
#pragma omp parallel for private(j) collapse(2)
for (i = 0; i < 4; i++)
for (j = 0; j < 100; j++)
实际上,这是显示何时使用崩溃的一个很好的例子。外循环只有四个迭代。如果您有四个以上的线程,那么将浪费一些线程。但是,当您合拢时,线程将在400次迭代之间分配,这可能比线程数大得多。使用崩溃的另一个原因是负载分布不均。如果只使用了四个迭代,而第四次迭代则花费了大部分时间,则其他线程将等待。但是,如果使用400次迭代,则负载可能会得到更好的分配。
您可以像这样手动为上面的代码融合一个循环
#pragma omp parallel for
for(int n=0; n<4*100; n++) {
int i = n/100; int j=n%100;
Here是显示如何用手融合三重熔断环的示例。
最后,here是显示如何融合未定义
collapse
的三角形循环的示例。这是在OP问题中将矩形环映射到三角形环的解决方案。这可用于熔合OP的三角回路。
//int n = 4;
for(int k=0; k<n*(n+1)/2; k++) {
int i = k/(n+1), j = k%(n+1);
if(j>i) i = n - i -1, j = n - j;
printf("(%d,%d)\n", i,j);
}
这适用于任何n值。
OP问题的 map 来自
(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),
(3,0), (3,1), (3,2), (3,3),
至
(0,0), (3,3), (3,2), (3,1), (3,0),
(1,0), (1,1), (2,2), (2,1), (2,0),
对于n的奇数值, map 并非完全是矩形,但公式仍然有效。
例如n = 3从
(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),
至
(0,0), (2,2), (2,1), (2,0),
(1,0), (1,1),
这是测试此代码
#include <stdio.h>
int main(void) {
int n = 4;
for(int i=0; i<n; i++) {
for(int j=0; j<=i; j++) {
printf("(%d,%d)\n", i,j);
}
}
puts("");
for(int k=0; k<n*(n+1)/2; k++) {
int i = k/(n+1), j = k%(n+1);
if(j>i) i = n - i - 1, j = n - j;
printf("(%d,%d)\n", i,j);
}
}
关于c - 了解openmp中的崩溃子句,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/28482833/