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

C++ 外部函数如何使用设备内存中的变量?,c++,cuda,gpgpu,openacc,pgi,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

在此代码中:

#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;
}

我不明白为什么指定
存在
会导致上述故障。我向NVVP检查了
value
enter data
指令中只复制一次,即在
intfun
中的
parallel
指令中不会再次复制。OpenACC是如何发挥其魔力的?

您再次被自己的语法和已经指出给您的东西弄糊涂了

intfun
中的
value
与您在
main
中执行的
copyin(value)
不同。函数调用按值传递
value
,这意味着它将复制它。因此,将它添加到
present()
子句没有意义,因为它不在设备上。编译器必须复制它。(当您根本不提及它时,编译器会自动识别出它是需要的,并为您复制它。)

设备上存在的项目是
main
-范围变量
,它不被
intfun
使用。给所有变量取相同的名称可能无助于理解这一点

为了演示这一点,让我们通过引用而不是通过值传递
value

$cat main 8.cpp
#包括
void intfun(int*变量、int和value){
#pragma acc parallel present(变量[:1],值)num_bangs(1)num_workers(1)
{
*变量=值;
}
}
int main(){
int-var,值=29;
#pragma acc输入数据创建(var)copyin(值)
intfun(风险值和价值);
#pragma acc退出数据复制(var)删除(值)

std::cout您再次被自己的语法和已经向您指出的内容弄糊涂了

intfun
中的
value
与您在
main
中执行的
copyin(value)
中的
value
不同。函数调用按值传递
value
,这意味着它复制了它。因此将它添加到
present()
子句没有任何意义,因为它不在设备上。编译器必须将其复制进来。(当您根本不提及它时,编译器会自动识别出它是需要的,并为您复制。)

设备上的项目是
main
-范围变量
,它不被
intfun
使用。给所有变量取相同的名称可能无助于您理解这一点

为了演示这一点,让我们通过引用而不是通过值传递
value

$cat main 8.cpp
#包括
void intfun(int*变量、int和value){
#pragma acc parallel present(变量[:1],值)num_bangs(1)num_workers(1)
{
*变量=值;
}
}
int main(){
int-var,值=29;
#pragma acc输入数据创建(var)copyin(值)
intfun(风险值和价值);
#pragma acc退出数据复制(var)删除(值)

std::那么我不明白为什么在我的源代码示例中,如果我省略了
copyin(值)
delete(值),那么
value
不会复制到设备上
main
中的pragmas中。设备从何处检索29的值?它存储在主机内存中,因此必须在某个时候复制到设备内存中。我在回答中已经说过,如果忽略任何
,编译器会自动识别
是必需的它将自动为它生成所需的副本。只有当您在重写此行为之前指定
present
时,事情才会中断。如果您有一个新问题,即您不理解的其他问题,它基于与问题中显示的不同的代码,您可能会提出一个新的问题离子。
copyin(值)
main
中的
与您的原始代码无关,没有它,您的原始代码就可以正常工作。我已与NVVP验证,在
main
中省略
value
的显式
copyin
会导致主机到设备的数据传输。因此,我对设备从何处获得
value的值感到困惑来自。它可以作为内核参数传递。感谢这个答案,它帮助我弄明白了一些东西。我想在你说“已经向你指出了什么”时提到这一点,它只适用于可能从您所写内容中受益的众多人中的一人。然后,我不明白为什么在我的源代码示例中,如果我省略了
copyin(value)
delete(value),那么
值就不会复制到设备上
main
中的pragmas中。设备从何处检索29的值?它存储在主机内存中,因此必须在某个时候复制到设备内存中。我在回答中已经说过,如果忽略任何
,编译器会自动识别
是必需的它将自动为它生成所需的副本。只有当您在重写此行为之前指定
present
时,事情才会中断。如果您有一个新问题,即您不理解的其他问题,它基于与问题中显示的不同的代码,您可能会提出一个新的问题离子。
copyin(值)
main
中的
与您的原始代码无关,没有它,您的原始代码就可以正常工作。我已与NVVP验证,在
main
中省略
value
的显式
copyin
会导致主机到设备的数据传输。因此,我对设备从何处获得
value的值感到困惑从。它可以作为内核参数传递。感谢这个答案,它帮助我弄明白了一些东西。我想提到的是,当你说“已经向你指出了什么”时,它适用于
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
$ 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
$