“task_reduction”和“约简(约简-修饰符,缩减标识符:列表)”与任务约简-修饰符相同吗?如果是相同的,那么为什么我们需要“任务减少”呢?
“in_reduction”在做什么?在文本中说,“in_reduction子句指定任务参与缩减”,但这意味着什么呢?在“in_reduction”中,我们需要与减缩相同的子句。
in_reduction(identifier : list)但是,如果我们可以将约简变量放在“列表”中,那么“任务参与约简”.会做什么呢?
我可以想象还原是如何工作的,但我无法想象使用“in_ reduction”。我们为什么要那样做?
======================================
我举了个例子。这个代码应该给出偶数的num和。
#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?
发布于 2022-01-14 18:20:01
任务约简的工作方式是,任务需要知道将其本地结果贡献到哪里。因此,您需要做的是让一个任务组“创建”缩减,然后让任务对其做出贡献:
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子句。
更新(以原始海报覆盖编辑):
代码的问题是,现在发生了两件事(请参阅更新代码中的内联注释):
#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构造,如下所示:
#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);
}在我的第一个答案中,我没有向任务中添加一个正确的firstprivate或private子句。那件事真对不起。
https://stackoverflow.com/questions/70712362
复制相似问题