首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >OpenMP: task_reduction=reduction?什么是“减缩”?

OpenMP: task_reduction=reduction?什么是“减缩”?
EN

Stack Overflow用户
提问于 2022-01-14 14:45:58
回答 1查看 184关注 0票数 0

“task_reduction”和“约简(约简-修饰符,缩减标识符:列表)”与任务约简-修饰符相同吗?如果是相同的,那么为什么我们需要“任务减少”呢?

“in_reduction”在做什么?在文本中说,“in_reduction子句指定任务参与缩减”,但这意味着什么呢?在“in_reduction”中,我们需要与减缩相同的子句。

代码语言:javascript
复制
in_reduction(identifier : list)

但是,如果我们可以将约简变量放在“列表”中,那么“任务参与约简”.会做什么呢?

我可以想象还原是如何工作的,但我无法想象使用“in_ reduction”。我们为什么要那样做?

======================================

我举了个例子。这个代码应该给出偶数的num和。

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char* argv[]){

        int Array [10]= {0,1,2,3,4,5,6,7,8,9};
        int Array_length = 10;
        int counter = 0;
        int result = 0;

        #pragma omp parallel
        #pragma omp single 

        {
        #pragma omp taskgroup task_reduction(+:result)
        //#pragma omp parallel reduction(task,+:result) this can work same as taskgroup task_reduction?
        {
             while (Array_length!=counter){
                  if (counter%2==0){
                      #pragma omp task in_reduction(+:result)
                      {
                          result+=Array[counter];
                      }
                  }else {
                          result+=Array[counter];
                  }
                  counter=counter+1;
             }
        }
    }
    printf("The sum of all array elements is equal to %d.\n", result);
}

我也做了一个例子,这样我就能想象出我的理解。

所以…task_reduction创建了一个约简,这样局部结果才能被贡献,只有任务用in_reduction才能参与到约简的贡献中?

如果我的理解是正确的,那么这段代码的结果应该是20。但是,我的代码给出了45,这是0到9的总和。

我在哪里犯了个错误?

顺便问一下,如果我根本没有写“in_reduction”,会发生什么呢?那么结果是0?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-14 18:20:01

任务约简的工作方式是,任务需要知道将其本地结果贡献到哪里。因此,您需要做的是让一个任务组“创建”缩减,然后让任务对其做出贡献:

代码语言:javascript
复制
void example() {
    int result = 0;
#pragma omp parallel   // create parallel team
#pragma omp single     // have only one task creator
    {
        #pragma omp taskgroup task_reduction(+:result)
        {
            while(have_to_create_tasks()) {
                #pragma omp task in_reduction(+:result)
                {   // this tasks contribute to the reduction
                    result = do_something();
                }
                #pragma omp task firstprivate(result)
                {   // this task does not contribute to the reduction
                    result = do_something_else();
                }
            }
        }
    }
}

因此,in_reduction对于一个任务来说是必需的,它可以帮助由包围taskgroup区域的task_reduction子句创建的缩减。

reduction子句不能与task构造一起使用,而只能用于工作共享结构和其他循环结构。

唯一具有reduction子句的任务结构是taskloop构造,它用于隐藏task_reduction构造的捷径,该构造包含它创建的所有循环构造,然后还有一个隐藏的in_reduction子句。

更新(以原始海报覆盖编辑):

代码的问题是,现在发生了两件事(请参阅更新代码中的内联注释):

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char* argv[]){
    int Array [10]= {0,1,2,3,4,5,6,7,8,9};
    int Array_length = 10;
    int counter = 0;
    int result = 0;

    #pragma omp parallel
    #pragma omp single
    {
        #pragma omp taskgroup task_reduction(+:result)
        {
            // "result" is a shared variable in this parallel region
            while (Array_length!=counter) {
                if (counter%2==0){
                    #pragma omp task in_reduction(+:result)
                    {
                        // This task will contribute to the reduction result
                        // as you would expect.
                        result+=Array[counter];
                    }
                } else {
                    // This addition to "result" is performed by the "single"
                    // thread and thus hits the shared variable.  You can see
                    // this when you print the address of "result" here
                    // and before the parallel region.
                    result+=Array[counter];
                }
                counter=counter+1;
            }
        } // Here the "single" thread waits for the taskgroup to complete
          // and the reduction to happen.  So, here the shared variable
          // "result" is added to the value of "result" coming from the
          // task reduction.  So, result = 25 from the "single" thread and
          // result = 20 are added up to result =45
    }
    printf("The sum of all array elements is equal to %d.\n", result);
}

任务减少结束时的添加似乎是一种竞争条件,因为来自single线程的更新和来自任务组末尾的更新是不同步的。我猜竞赛不会出现,因为代码太快,无法清楚地公开它。

要修复代码,还必须在更新奇数时使用task构造,如下所示:

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <omp.h>
int main(int argc, char* argv[]){
    int Array [10]= {0,1,2,3,4,5,6,7,8,9};
    int Array_length = 10;
    int counter = 0;
    int result = 0;

    #pragma omp parallel
    #pragma omp single
    {
        #pragma omp taskgroup task_reduction(+:result)
        {
            // "result" is a shared variable in this parallel region
            while (Array_length!=counter) {
                if (counter%2==0){
                    #pragma omp task in_reduction(+:result)
                    {
                        // This task will contribute to the reduction result
                        // as you would expect.
                        result+=Array[counter];
                    }
                } else {
                    #pragma omp task firstprivate(result)
                    {
                        // "result" is now a task-local variable that is not
                        // shared.  If you remove the firstprivate, then the
                        // race condition on the shared variable "result" is
                        // back.
                        result+=Array[counter];
                    }
                }
                counter=counter+1;
            }
        } // Here the "single" thread waits for the taskgroup to complete
          // and the reduction to happen.  So, here the shared variable
          // "result" is added to the value of "result" coming from the
          // task reduction.  So, result = 25 from the "single" thread and
          // result = 20 are added up to result =45
    }
    printf("The sum of all array elements is equal to %d.\n", result);
}

在我的第一个答案中,我没有向任务中添加一个正确的firstprivateprivate子句。那件事真对不起。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70712362

复制
相关文章

相似问题

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