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
$