首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >理解openmp中的clause子句

理解openmp中的clause子句
EN

Stack Overflow用户
提问于 2015-02-13 00:35:46
回答 2查看 50.3K关注 0票数 36

我遇到了一段OpenMP代码,其中包含崩溃子句,这对我来说是第一次。我试图理解它的含义,但我认为我还没有完全理解它的含义;我找到的一个定义是:

COLLAPSE:指定嵌套循环中有多少循环应该折叠到一个大的迭代空间中,并根据schedule子句进行划分。所有相关循环中迭代的顺序执行决定了折叠迭代空间中迭代的顺序。

我想我明白了这意味着什么,所以我尝试了下面这个简单的程序:

代码语言:javascript
复制
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());

产生了

代码语言:javascript
复制
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)子句。我本希望在前两列中得到相同的结果,但现在在最后一列中有相同数量的01

代码语言:javascript
复制
0 0 0
1 0 0
2 0 1
3 0 1

所以我的问题是:

  1. 我的代码中发生了什么?
  2. 我应该在什么情况下使用collapse您可以提供一个示例,说明使用和不使用

之间的区别?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-02-13 01:21:11

代码的问题在于内循环的迭代依赖于外循环。根据绑定一节和collapse子句描述下的OpenMP规范:

如果任何相关循环的执行更改了用于计算任何迭代计数的任何值,则行为未指定。

当情况不是这样时,您可以使用折叠,例如,对于方形循环

代码语言:javascript
复制
#pragma omp parallel for private(j) collapse(2)
for (i = 0; i < 4; i++)
    for (j = 0; j < 100; j++)

事实上,这是一个很好的例子来说明何时使用折叠。外部循环只有四次迭代。如果你有四个以上的线程,那么一些线程会被浪费掉。但是,当您折叠时,线程将分布在400次迭代中,这很可能比线程的数量多得多。使用折叠的另一个原因是如果负载分布不均匀。如果您只使用了四次迭代,并且第四次迭代花费了大部分时间,则其他线程将等待。但是,如果您使用400次迭代,负载可能会更好地分布。

您可以为上面的代码手工融合一个循环,如下所示

代码语言:javascript
复制
#pragma omp parallel for
for(int n=0; n<4*100; n++) {
    int i = n/100; int j=n%100;

Here是一个演示如何手工融合三重熔断环路的示例。

最后,here是一个示例,展示了如何融合没有定义collapse的三角形循环。

这是一个解决方案,它将一个矩形循环映射到OPs问题中的三角形循环。这可以用来熔断OPs三角环路。

代码语言:javascript
复制
//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值都有效。

运维问题的地图来自

代码语言:javascript
复制
(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),
(3,0), (3,1), (3,2), (3,3),

代码语言:javascript
复制
(0,0), (3,3), (3,2), (3,1), (3,0),
(1,0), (1,1), (2,2), (2,1), (2,0),

对于n的奇数值,映射不完全是矩形,但公式仍然有效。

例如,n=3从

代码语言:javascript
复制
(0,0),
(1,0), (1,1),
(2,0), (2,1), (2,2),

代码语言:javascript
复制
(0,0), (2,2), (2,1), (2,0),
(1,0), (1,1),

下面是测试这一点的代码

代码语言:javascript
复制
#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);
    }
}
票数 45
EN

Stack Overflow用户

发布于 2018-03-03 01:40:32

如果您的目的是通过增加行来平衡负载,假设每个项目的工作负载是规则的或分散的,那么将行索引对半折叠并忘记collapse子句如何?

代码语言:javascript
复制
#pragma omp for
for (int iy0=0; iy0<n; ++iy0){
  int iy = iy0;
  if (iy0 >= n/2) iy = n-1 -iy0 +n/2;
  for (int ix=iy+1; ix<n; ++ix){
    work(ix, iy);
  }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/28482833

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档