外部函数使用的设备内存中的变量如何?

时间:2014-09-23 20:14:14

标签: c++ cuda gpgpu openacc pgi

在此代码中:

#include <iostream>

void intfun(int * variable, int value){
    #pragma acc parallel present(variable[:1]) num_gangs(1) num_workers(1)
    {
        *variable = value;
    }
}

int main(){
    int var, value = 29;

    #pragma acc enter data create(var) copyin(value)
        intfun(&var,value);
    #pragma acc exit data copyout(var) delete(value)

    std::cout << var << std::endl;
}

int value如何识别intfun设备内存?如果我在present(variable[:1]) pragma中将present(variable[:1],value)替换为intfun,则会出现以下运行时错误:

FATAL ERROR: data in PRESENT clause was not found on device 1: name=_43144_33_value
 file:/opt/pgi/linux86-64/14.9/include/CC/iostream intfun__FPii line:5
Present table dump for device[1]: NVIDIA Tesla GPU 1, compute capability 3.5
host:0x7fffc11faa28 device:0x2303f20200 size:4 presentcount:1 line:14 name:_43152_14_value
host:0x7fffc11faa34 device:0x2303f20000 size:4 presentcount:2 line:14 name:_43152_9_var

我不明白为什么指定value present会导致上述失败。我查看了NVVP,value仅在enter data指令中复制了一次,即它不会再次复制到parallel中的intfun指令中。 OpenACC如何发挥其神奇作用?

1 个答案:

答案 0 :(得分:4)

您已经通过自己的语法和已经指出的内容再次感到困惑。

value中的{p> intfun与您在valuecopyin(value)的{​​{1}}不同。函数调用按值传递main,这意味着它会生成副本。因此,将其添加到value子句没有任何意义,因为它在设备上不存在。编译器必须将其复制。(当你完全没有提到它时,编译器会自动识别它是否需要并为你复制它。)

设备上存在的项目是present() - 范围变量mainvalue 未使用 }。给所有变量赋予相同的名称可能无助于您理解这一点。

为了证明这一点,让我们通过引用而不是按值传递intfun

value

现在主要范围变量$ cat main8.cpp #include <iostream> void intfun(int * variable, int &value){ #pragma acc parallel present(variable[:1],value) num_gangs(1) num_workers(1) { *variable = value; } } int main(){ int var, value = 29; #pragma acc enter data create(var) copyin(value) intfun(&var,value); #pragma acc exit data copyout(var) delete(value) std::cout << var << std::endl; } [user2@dc12 misc]$ pgcpp -acc -Minfo main8.cpp intfun(int *, int &): 5, Generating present(variable[:1]) Generating present(value[:]) Accelerator kernel generated Generating Tesla code main: 14, Generating enter data copyin(value) Generating enter data create(var) 17, Generating exit data delete(value) Generating exit data copyout(var) $ ./a.out 29 $ 在设备上,编译器知道它,它将由value直接使用,并将其添加到intfun子句是合法的,功能