OpenACC 2.0例程:数据位置

时间:2014-11-11 20:19:01

标签: gpgpu openacc

使用以下代码,该代码说明了在加速器上调用简单例程,使用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}}的设备副本?我们如何强制使用设备副本?

3 个答案:

答案 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。这是一种更准确的方式。

例程将使用设备存储器中的日期。