1

为什么下面的代码:

#include <iostream>

int main(int argc, char const *argv[])
{
    int sum = 0;
    int *array;
    array = new int [100];

    #pragma acc enter data create(array[0:100],sum)

    #pragma acc parallel loop present(array[0:100])
    for (int i = 0; i < 100; ++i)
    {
        array[i] = 1;
    }

    #pragma acc parallel loop present(array[0:100],sum) reduction(+:sum)
    for (int i = 0; i < 100; ++i)
    {
        sum += array[i];
    }

    #pragma acc exit data delete(array[0:100]) copyout(sum)

    std::cout << sum << std::endl;

    return 0;
}

每次执行都返回不同的结果?

$ pgcpp -acc -Minfo main.cpp
main:
      7, Generating enter data create(sum)
         Generating enter data create(array[:100])
         Generating present(array[:100])
         Accelerator kernel generated
         12, #pragma acc loop gang, vector(256) /* blockIdx.x threadIdx.x */
      7, Generating Tesla code
     15, Generating present(array[:100])
         Generating present(sum)
         Accelerator kernel generated
         18, #pragma acc loop gang, vector(256) /* blockIdx.x threadIdx.x */
         20, Sum reduction generated for sum
     15, Generating Tesla code
     25, Generating exit data copyout(sum)
         Generating exit data delete(array[:100])
$ ./a.out
100
$ ./a.out
200
$ ./a.out
300
$ ./a.out
400

根据 OpenACC 标准:

在退出数据指令上,数据被复制回本地内存并被释放。

看起来它sum没有被释放,而是在程序的每次运行时重新使用(并增加)。此外,指令中的+运算符reduction将归约变量初始化为0,因此即使sum没有在执行之间释放,也不应该发生这种情况。

我可以通过在指令中使用copyin而不是createfor来避免这种行为,或者在单个 gang、单个工作内核中设置:sumenter datasum = 0

#pragma acc parallel present(sum) num_gangs(1) num_workers(1)
sum = 0;

但这并不令人满意,因为它需要昂贵的主机到设备数据复制,或者内核启动。为什么我的程序会这样?

4

1 回答 1

2

您误解了归约运算符初始化值的含义。参考openACC 规范,第 20-21 页:

并行构造上允许使用归约子句。它指定一个归约运算符和一个或多个标量变量。对于每个变量,为每个并行组创建一个私有副本,并为该操作员初始化。在区域的末尾,使用归约算子组合每个 gang 的值,并将结果与​​原始变量的值组合并存储在原始变量中。

这意味着整个还原问题被分解成小块,每个小块都由一个帮派处理。由 gang 处理的部分问题将使用减少变量的指示初始化值。但是,当创建最终结果时,每个帮派的单个结果将与原始变量的值(sum在您的情况下)相结合,这就是结果。

因此,您必须正确初始化sum,也许使用您在问题中概述的方法之一。

此外,虽然这不是问题的症结,但请注意,无论是释放还是分配都不会对内存内容产生任何影响。在该位置分配的新变量,如果没有适当的初始化,将在该位置获取当前的值。

于 2014-09-27T17:53:20.983 回答