使用以下代码,该代码说明了在加速器上调用简单例程,使用OpenACC 2.0的routine
指令在设备上编译:
#include <iostream>
#pragma acc routine
int function(int *ARRAY,int multiplier){
int sum=0;
#pragma acc loop reduction(+:sum)
for(int i=0; i<10; ++i){
sum+=multiplier*ARRAY[i];
}
return sum;
}
int main(){
int *ARRAY = new int[10];
int multiplier = 5;
int out;
for(int i=0; i<10; i++){
ARRAY[i] = 1;
}
#pragma acc enter data create(out) copyin(ARRAY[0:10],multiplier)
#pragma acc parallel present(out,ARRAY[0:10],multiplier)
if (function(ARRAY,multiplier) == 50){
out = 1;
}else{
out = 0;
}
#pragma acc exit data copyout(out) delete(ARRAY[0:10],multiplier)
std::cout << out << std::endl;
}
function
如何在并行区域内调用ARRAY[0:10]
和multiplier
时使用{{1}}和{{1}}的设备副本?我们如何强制使用设备副本?
答案 0 :(得分:1)
在设备区域(代码中的parallel
)内调用例程时,设备上的线程会调用它,这意味着这些线程只能访问设备上的数组。编译器实际上可能选择内联该函数,或者它可能是设备端函数调用。这意味着您可以知道当从设备调用该函数时,它将接收数据的设备副本,因为该函数实质上是从并行区域继承present
数据子句。如果你仍然想让自己说服你在设备内部运行一次,那么你可以打电话给acc_on_device
,但这只会告诉你你在加速器上运行,而不是你收到设备指针。
如果你想强制使用更多的设备副本,你可以制定例程nohost
,这样从技术上讲从主机调用就无效了,但这并不是真的有效。您要问的是,在GPU上检查阵列是否真的是一个设备阵列。
请记住,并行区域内不在loop
内的任何代码都将运行 gang-redundantly ,因此写入out
可能是竞争条件,除非您碰巧与一个帮派一起运行或者您使用atomic
写信。
答案 1 :(得分:0)
基本上,当你涉及&#34;数据&#34;子句,设备将创建/复制数据到设备存储器,然后是用&#34; acc例程&#34;定义的代码块。将在设备上执行。请注意,与多线程(OpenMP)不同,主机和设备之间的内存不共享。是的,&#34;功能&#34;将使用ARRAY和乘数的设备副本,只要它在数据段下。希望这可以帮助! :)
答案 2 :(得分:0)
您应该为该功能分配一个并行级别,例如gang / worker / vector。这是一种更准确的方式。
例程将使用设备存储器中的日期。