访问指向其他向量的向量在GPU上

时间:2013-05-31 09:54:26

标签: c++ pointers cuda gpu cula

所以这是我的一个问题的后续问题,目前在一些代码的CPU版本中,我有许多看起来如下的东西:

for(int i =0;i<N;i++){

    dgemm(A[i], B[i],C[i], Size[i][0], Size[i][1], Size[i][2], Size[i][3], 'N','T');

}

其中A [i]将是某种尺寸的2D矩阵。

我希望能够在使用CULA的GPU上做到这一点(我不只是做乘法,所以我需要在CULA中进行线性代数运算),例如:

 for(int i =0;i<N;i++){
        status = culaDeviceDgemm('T', 'N', Size[i][0], Size[i][0], Size[i][0], alpha, GlobalMat_d[i], Size[i][0], NG_d[i], Size[i][0], beta, GG_d[i], Size[i][0]);
}

但是我想在程序开始时将我的B存储在GPU上,因为它们没有改变,所以我需要一个包含指向构成我B的矢量集的指针。

我目前有以下代码编译:

double **GlobalFVecs_d;
double **GlobalFPVecs_d;

extern "C" void copyFNFVecs_(double **FNFVecs, int numpulsars, int numcoeff){


  cudaError_t err;
  GlobalFPVecs_d = (double **)malloc(numpulsars * sizeof(double*));
 err = cudaMalloc( (void ***)&GlobalFVecs_d, numpulsars*sizeof(double*) );
 checkCudaError(err);

    for(int i =0; i < numpulsars;i++){
         err = cudaMalloc( (void **) &(GlobalFPVecs_d[i]), numcoeff*numcoeff*sizeof(double) );
         checkCudaError(err);    
         err = cudaMemcpy( GlobalFPVecs_d[i], FNFVecs[i], sizeof(double)*numcoeff*numcoeff, cudaMemcpyHostToDevice );
         checkCudaError(err);   
        }

         err = cudaMemcpy( GlobalFVecs_d, GlobalFPVecs_d, sizeof(double*)*numpulsars, cudaMemcpyHostToDevice );
         checkCudaError(err);

}

但如果我现在尝试使用以下方式访问它:

 dim3 dimBlock(BLOCK_SIZE, BLOCK_SIZE);
 dim3 dimGrid;//((G + dimBlock.x - 1) / dimBlock.x,(N + dimBlock.y - 1) / dimBlock.y);
 dimGrid.x=(numcoeff + dimBlock.x - 1)/dimBlock.x;
 dimGrid.y = (numcoeff + dimBlock.y - 1)/dimBlock.y;

 for(int i =0; i < numpulsars; i++){
    CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFVecs_d[i], numpulsars, numcoeff, i);
 }

它在此处出现故障,这不是如何获取数据的吗?

我正在调用的内核函数只是:

__global__ void CopyPPFNF(double *FNF_d, double *PPFNF_d, int numpulsars, int numcoeff, int thispulsar) {

    // Each thread computes one element of C
    // by accumulating results into Cvalue




    int row = blockIdx.y * blockDim.y + threadIdx.y;
    int col = blockIdx.x * blockDim.x + threadIdx.x;

    int subrow=row-thispulsar*numcoeff;
    int subcol=row-thispulsar*numcoeff;

     __syncthreads();
    if(row >= (thispulsar+1)*numcoeff || col >= (thispulsar+1)*numcoeff) return;
    if(row < thispulsar*numcoeff || col < thispulsar*numcoeff) return;


    FNF_d[row * numpulsars*numcoeff + col] += PPFNF_d[subrow*numcoeff+subcol];

}

我做得不对?注意最终我还想做第一个例子,在每个GlobalFVecs_d [i]上调用cula函数,但是现在甚至不能这样做。

你认为这是最好的方法吗?如果有可能只是传递CULA函数一片大的连续向量我可以做到,但我不知道它是否支持。

干杯 林德利

1 个答案:

答案 0 :(得分:0)

改变这个:

CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFVecs_d[i], numpulsars, numcoeff, i);

到此:

CopyPPFNF<<<dimGrid, dimBlock>>>(PPFMVec_d, GlobalFPVecs_d[i], numpulsars, numcoeff, i);

我相信它会奏效。

处理指针的方法大多是正确的。但是,当您将GlobalFVecs_d[i]放入参数列表时,您强制内核设置代码(在主机上运行)取GlobalFVecs_d(设备指针,使用cudaMalloc创建),添加对指针值进行适当缩放i,然后取消引用结果指针以检索要作为参数传递给内核的值。但我们不允许取消引用主机代码中的设备指针。

但是,因为您的方法大多是正确的,所以您有一个方便的并行数组 相同的指针驻留在主机上。这个数组(GlobalFPVecs_d)是允许我们在主机代码中取消引用以检索结果设备指针以传递给内核的。

这是一个有趣的错误,因为通常内核不会出错(尽管它们可能会抛出错误),因此内核调用行上的seg错误是不常见的。但在这种情况下,seg错误发生在内核设置代码中,而不是内核本身。