OpenACC2.0-routine

對於OpenCC1.0中,沒有定義函數調用,用戶自定義的函數調用只能通過內聯(inline)的方式,在編譯時需要添加編譯選項:-Minline.

在OpenACC2.0中,新添加了routine導語,來實現用戶自定義函數調用。下面我們來看一個例子:

#include<stdio.h>

#pragma acc routine worker
int sum(int n,float *A)
{
        int i;
        float s=0.0f;
        #pragma acc loop vector reduction(+:s)
        for(i=0;i<n;i++){
                s=s+A[i];
        }
        return s;
}

int main()
{
        float *X,*Y;
        X=(float*)malloc(sizeof(float)*100*200);
        Y=(float*)malloc(sizeof(float)*100);
        int j,i;
        for(j=0;j<100;j++){
                for(i=0;i<200;i++){
                        X[j*200+i]=j;
                }
        }
        #pragma acc parallel copyout(Y[0:100]) copyin(X[0:100*200])
        {
                #pragma acc loop gangs
                for(j=0;j<100;j++){
                        Y[j]=sum(200,(X+j*200));
                }
        }

        for(j=0;j<10;j++){
                printf("Y[%d]=%f\n",j,Y[j]);
        }
        return 0;
}

例子的功能很簡單,x是100列200行的數組,需要求出x中每一行的大小。對於這個例子,把x的每一列,映射到OpenACC的gang級別並行(對於CUDA來說是block,對於OpenCL來說是workgroup),再對於每一行求和來說再把其映射到OpenACC的worker級別並行。
     程序編譯輸出如下:

[root@lucas routine]# pgcc -o routine routine.c -acc -Minfo -ta=nvidia,cc20
NOTE: your trial license will expire in 13 days, 8.59 hours.
PGC-W-0155-Pointer value created from a nonlong integral type  (routine.c: 18)
PGC-W-0155-Pointer value created from a nonlong integral type  (routine.c: 19)
sum:
      0, Generating acc routine worker
          9, #pragma acc loop  /* threadIdx.x threadIdx.y */
      0, Generating NVIDIA code
main:
     22, Memory set idiom, loop replaced by call to __c_mset4
     26, Generating copyout(Y[0:100])
         Generating copyin(X[0:20000])
         Accelerator kernel generated
         29, #pragma acc loop gang /* blockIdx.x */
     26, Generating NVIDIA code
PGC/x86-64 Linux 14.2-0: compilation completed with warnings
[root@lucas routine]# 

PGI_ACC_TIME設置爲1時,程序輸出如下:

[root@lucas routine]# ./routine 
Y[0]=0.000000
Y[1]=200.000000
Y[2]=400.000000
Y[3]=600.000000
Y[4]=800.000000
Y[5]=1000.000000
Y[6]=1200.000000
Y[7]=1400.000000
Y[8]=1600.000000
Y[9]=1800.000000

Accelerator Kernel Timing /root/OpenACC/routine/routine.c
  main  NVIDIA  devicenum=0
    time(us): 450
    26: data region reached 1 time
        26: data copyin reached 1 time
             device time(us): total=33 max=33 min=33 avg=33
        34: data copyout reached 1 time
             device time(us): total=14 max=14 min=14 avg=14
    26: compute region reached 1 time
        26: kernel launched 1 time
            grid: [100]  block: [1]
             device time(us): total=403 max=403 min=403 avg=403
            elapsed time(us): total=414 max=414 min=414 avg=414
[root@lucas routine]# 

  需要注意的是routine導語必須包含gang,worker,vector或seq子句,來指定調用函數的上下文,和允許的最大任務分享的級別。    例如,有worker子句的routine導語可以包含worker,vector和seq loops,但是不能包含gang loops。同樣,該routine不能從worker或vector loop中被調用。對於不包含 gang, worker ,vector 子句的routine,那必須有seq子句,這樣該routine可以隨便在哪調用。

發佈了40 篇原創文章 · 獲贊 7 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章