CUDA设备指针操作

时间:2011-05-06 09:36:50

标签: pointers cuda

我用过:

float *devptr;
//...
cudaMalloc(&devptr, sizeofarray);
cudaMemcpy(devptr, hostptr, sizeofarray, cudaMemcpyHostToDevice);
在CUDA C中

分配和填充数组。 现在我正在尝试运行cuda内核,例如:

__global__ void kernelname(float *ptr)
{
   //...
}

在该数组中但具有偏移值。 在C / C ++中,它会像这样:

kernelname<<<dimGrid, dimBlock>>>(devptr+offset);

但是,这似乎不起作用。

有没有办法在不将单独的参数中的偏移值发送到内核并在内核代码中使用该偏移量的情况下执行此操作? 关于如何做到这一点的任何想法?

2 个答案:

答案 0 :(得分:9)

指针算法在CUDA中运行得很好。您可以在主机代码中向CUDA指针添加一个偏移量,它将正常工作(记住偏移量不是字节偏移量,它是一个普通的单词或元素偏移量。)

编辑:一个简单的工作示例:

#include <cstdio>
int main(void)
{

    const int na = 5, nb = 4;
    float a[na] = { 1.2, 3.4, 5.6, 7.8, 9.0 };
    float *_a, b[nb];

    size_t sza = size_t(na) * sizeof(float);
    size_t szb = size_t(nb) * sizeof(float);

    cudaFree(0);

    cudaMalloc((void **)&_a, sza );
    cudaMemcpy( _a, a, sza, cudaMemcpyHostToDevice);
    cudaMemcpy( b, _a+1, szb, cudaMemcpyDeviceToHost);

    for(int i=0; i<nb; i++)
        printf("%d %f\n", i, b[i]);

    cudaThreadExit();
}

在这里,您可以看到第二个cudaMemcpy调用中的设备指针已经应用了一个单词/元素偏移量,以便从第二个单词开始复制,而不是第一个单词。

答案 1 :(得分:1)

指针算法确实适用于主机端代码,它在nvidia提供的示例代码中经常使用。

“设备中的线性存储器存在于40位地址空间中,因此单独分配的实体可以通过指针相互引用,例如,在二叉树中。”

阅读详情:http://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#ixzz4KialMz00

从性能原语(npp)文档中,指针算法的一个完美例子。

“4.5.1选择通道源图像指针 这是指向源图像的第一个像素内的感兴趣通道的指针。例如。如果pSrc是 指向三通道图像的ROI内的第一个像素的指针。使用适当的选择通道副本 原始人可以将该源图像的第二个通道复制到目标的第一个通道 pDst通过将指针偏移一个给出的图像: nppiCopy_8u_C3CR(pSrc + 1,nSrcStep,pDst,nDstStep,oSizeROI);“

*注意:这不会乘以每个数据元素的字节数,因为编译器知道指针的数据类型,并相应地计算地址。

在C和C ++中,指针运算可以如上所述或通过符号&amp; ptr [offset]完成(为了返回数据的设备存储器地址而不是值,值将不能从主机端代码在设备存储器上工作)。使用任何一种表示法时,都会自动处理数据类型的大小,并将偏移量指定为多个数据元素而不是字节。