Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/neo4j/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
OpenACC:如何从指向主机上相应数组的指针中选择设备上的数组_C_Arrays_Openacc_Pgcc - Fatal编程技术网

OpenACC:如何从指向主机上相应数组的指针中选择设备上的数组

OpenACC:如何从指向主机上相应数组的指针中选择设备上的数组,c,arrays,openacc,pgcc,C,Arrays,Openacc,Pgcc,我正在尝试使用OpenACC将现有的C代码卸载到GPU。在原始的CPU代码中,很多时候需要根据某个参数的值选择一个数据数组。下面给出了一个示例CPU代码: #include <stdio.h> #include <stdlib.h> void selectArray (int **F, int a); #define NN 1000 int *C, *D, *E; int main(void) { int *F, a = 10; // a is the p

我正在尝试使用OpenACC将现有的C代码卸载到GPU。在原始的CPU代码中,很多时候需要根据某个参数的值选择一个数据数组。下面给出了一个示例CPU代码:

#include <stdio.h>
#include <stdlib.h>


void selectArray (int **F, int a);

#define NN 1000
int *C, *D, *E;

int main(void)
{
    int *F, a = 10; // a is the parameter used to select the array

    C = (int *)malloc(NN * sizeof(int));
    D = (int *)malloc(NN * sizeof(int));
    E = (int *)malloc(NN * sizeof(int));

    for (int i = 0; i < NN; i++)
    {
        C[i] = 10;
        D[i] = 20;
    }

    selectArray(&F, a);

    for (int i = 0; i < NN; i++)
    {
       E[i] = 2 * F[i];
    }

    for (int i = 0; i < 200; i++)
       printf("%d %d \n", i, E[i]);

    return 0;

}

void selectArray(int **F, int a)
{
    if (a <= 15)
    {
        (*F) = C;
    }
    else
    {
        (*F) = D;
    }
}
对于OpenACC版本的代码,阵列C和D已经存在于GPU上,需要在根据参数a选择的阵列上进行进一步的计算

在实际代码中,数组C和D是在不同的函数中计算的,而不是在主函数中。我曾尝试在互联网上搜索来解决这个问题,但我找不到任何相关的例子。我正在Windows 10上使用PGI 19.10编译器。请求在这方面提供帮助。
提前感谢

您只需要在并行循环中添加一个presentF,而不需要在数据区域中包含F。由于acc present表的查找是按主机地址进行的,因此如果F与设备上现有的主机地址匹配,它将F与相同的设备地址相关联。但是,不要将F放在它自己的数据区域中,尤其不要删除它,因为它会在同一设备阵列上导致多个空闲

我对代码做了一些修改,使F在一种情况下指向C,在第二种情况下指向D

% cat test.c
#include <stdio.h>
#include <stdlib.h>

void selectArray(int **F, int a);

#define NN 1000
int *C, *D, *E;

int main(void)
{
    int *F, a = 10; // a is the parameter used to select the array

    C = (int *)malloc(NN * sizeof(int));
    D = (int *)malloc(NN * sizeof(int));
    E = (int *)malloc(NN * sizeof(int));

#pragma acc enter data create(C[:NN], D[:NN], E[:NN])
#pragma acc parallel loop present(C[:NN], D[:NN])
    for (int i = 0; i < NN; i++)
    {
        C[i] = 10;
        D[i] = 20;
    }

    for (a=10;a<=20;a+=10) {
       selectArray(&F, a);

#pragma acc parallel loop present(E,F)
       for (int i = 0; i < NN; i++)
       {
          E[i] = 2 * F[i]; //further calculations on selected array on GPU
       }
#pragma acc update host(E[:20])
       for (int i = 0; i < 20; i++)
       {
          printf("a=%d E[%d]=%d \n", a, i, E[i]);
       }
     }
#pragma acc exit data delete(C, D, E)
    return 0;
}

void selectArray(int **F, int a)
{
    if (a <= 15)
    {
        (*F) = C;
    }
    else
    {
        (*F) = D;
    }
}
% pgcc -ta=tesla -Minfo=accel test.c; a.out
main:
     17, Generating enter data create(D[:1000],E[:1000],C[:1000])
     18, Generating present(D[:1000],C[:1000])
         Generating Tesla code
         19, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
     28, Generating present(E[:],F[:])
         Generating Tesla code
         29, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
     34, Generating update self(E[:20])
     39, Generating exit data delete(E[:1],D[:1],C[:1])
a=10 E[0]=20
a=10 E[1]=20
a=10 E[2]=20
a=10 E[3]=20
a=10 E[4]=20
a=10 E[5]=20
a=10 E[6]=20
a=10 E[7]=20
a=10 E[8]=20
a=10 E[9]=20
a=10 E[10]=20
a=10 E[11]=20
a=10 E[12]=20
a=10 E[13]=20
a=10 E[14]=20
a=10 E[15]=20
a=10 E[16]=20
a=10 E[17]=20
a=10 E[18]=20
a=10 E[19]=20
a=20 E[0]=40
a=20 E[1]=40
a=20 E[2]=40
a=20 E[3]=40
a=20 E[4]=40
a=20 E[5]=40
a=20 E[6]=40
a=20 E[7]=40
a=20 E[8]=40
a=20 E[9]=40
a=20 E[10]=40
a=20 E[11]=40
a=20 E[12]=40
a=20 E[13]=40
a=20 E[14]=40
a=20 E[15]=40
a=20 E[16]=40
a=20 E[17]=40
a=20 E[18]=40
a=20 E[19]=40

你认为你的产出是什么?除了设置E的循环之后的额外}之外,我得到了我认为正确的答案,所有20个都是书面的,如果我修改a,所有40个都是。我在Linux上使用了19.10和GPU目标。先生,我在Windows编译器上也得到了同样的结果,我应该在问题中提到。然而,在实际代码中,F的删除引起了问题。Mat Colgrove对此问题提供了极好的解释和解决方案。
% cat test.c
#include <stdio.h>
#include <stdlib.h>

void selectArray(int **F, int a);

#define NN 1000
int *C, *D, *E;

int main(void)
{
    int *F, a = 10; // a is the parameter used to select the array

    C = (int *)malloc(NN * sizeof(int));
    D = (int *)malloc(NN * sizeof(int));
    E = (int *)malloc(NN * sizeof(int));

#pragma acc enter data create(C[:NN], D[:NN], E[:NN])
#pragma acc parallel loop present(C[:NN], D[:NN])
    for (int i = 0; i < NN; i++)
    {
        C[i] = 10;
        D[i] = 20;
    }

    for (a=10;a<=20;a+=10) {
       selectArray(&F, a);

#pragma acc parallel loop present(E,F)
       for (int i = 0; i < NN; i++)
       {
          E[i] = 2 * F[i]; //further calculations on selected array on GPU
       }
#pragma acc update host(E[:20])
       for (int i = 0; i < 20; i++)
       {
          printf("a=%d E[%d]=%d \n", a, i, E[i]);
       }
     }
#pragma acc exit data delete(C, D, E)
    return 0;
}

void selectArray(int **F, int a)
{
    if (a <= 15)
    {
        (*F) = C;
    }
    else
    {
        (*F) = D;
    }
}
% pgcc -ta=tesla -Minfo=accel test.c; a.out
main:
     17, Generating enter data create(D[:1000],E[:1000],C[:1000])
     18, Generating present(D[:1000],C[:1000])
         Generating Tesla code
         19, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
     28, Generating present(E[:],F[:])
         Generating Tesla code
         29, #pragma acc loop gang, vector(128) /* blockIdx.x threadIdx.x */
     34, Generating update self(E[:20])
     39, Generating exit data delete(E[:1],D[:1],C[:1])
a=10 E[0]=20
a=10 E[1]=20
a=10 E[2]=20
a=10 E[3]=20
a=10 E[4]=20
a=10 E[5]=20
a=10 E[6]=20
a=10 E[7]=20
a=10 E[8]=20
a=10 E[9]=20
a=10 E[10]=20
a=10 E[11]=20
a=10 E[12]=20
a=10 E[13]=20
a=10 E[14]=20
a=10 E[15]=20
a=10 E[16]=20
a=10 E[17]=20
a=10 E[18]=20
a=10 E[19]=20
a=20 E[0]=40
a=20 E[1]=40
a=20 E[2]=40
a=20 E[3]=40
a=20 E[4]=40
a=20 E[5]=40
a=20 E[6]=40
a=20 E[7]=40
a=20 E[8]=40
a=20 E[9]=40
a=20 E[10]=40
a=20 E[11]=40
a=20 E[12]=40
a=20 E[13]=40
a=20 E[14]=40
a=20 E[15]=40
a=20 E[16]=40
a=20 E[17]=40
a=20 E[18]=40
a=20 E[19]=40