OpenMP:task_reduction=减少?什么是 'in_reduction'?
OpenMP: task_reduction=reduction? What is 'in_reduction'?
是否'task_reduction'与'reduction ([ reduction-modifier ,] reduction
标识符:列表)'与任务缩减修饰符?
如果相同,那为什么我们需要'task_reduction'?
'in_reduction'在做什么?
文中说 'The in_reduction clause specifies that a task participates in a reduction '
但是,这是什么意思?在 'in_reduction' 中,我们需要与 reduction 相同的子句。
in_reduction(identifier : list)
但是如果我们可以在 'list' 中放置缩减变量,那么这对 'task participates in reduction' 有什么作用...?
我可以想象减少是如何工作的,但我无法想象 '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创建一个reduction,这样就可以贡献本地结果,只有in_reduction的任务才会参与Reduction的贡献?
如果我没理解错的话,这段代码的结果应该是 20。但是,我的代码给出了 45,这是 0 到 9 的总和。
我哪里弄错了?
顺便说一句,如果我根本不写'in_reduction'会怎样?那么结果是0?
任务缩减的工作方式是任务需要知道将其本地结果贡献给哪里。所以,你要做的是有一个任务组来“创造”减少,然后让任务为它做出贡献:
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
子句。我很抱歉。
是否'task_reduction'与'reduction ([ reduction-modifier ,] reduction 标识符:列表)'与任务缩减修饰符? 如果相同,那为什么我们需要'task_reduction'?
'in_reduction'在做什么? 文中说 'The in_reduction clause specifies that a task participates in a reduction ' 但是,这是什么意思?在 'in_reduction' 中,我们需要与 reduction 相同的子句。
in_reduction(identifier : list)
但是如果我们可以在 'list' 中放置缩减变量,那么这对 'task participates in reduction' 有什么作用...?
我可以想象减少是如何工作的,但我无法想象 '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创建一个reduction,这样就可以贡献本地结果,只有in_reduction的任务才会参与Reduction的贡献?
如果我没理解错的话,这段代码的结果应该是 20。但是,我的代码给出了 45,这是 0 到 9 的总和。
我哪里弄错了?
顺便说一句,如果我根本不写'in_reduction'会怎样?那么结果是0?
任务缩减的工作方式是任务需要知道将其本地结果贡献给哪里。所以,你要做的是有一个任务组来“创造”减少,然后让任务为它做出贡献:
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
子句。我很抱歉。