2011-05-06 116 views
2

我使用: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); 

然而,这似乎并没有工作。

有没有办法做到这一点,而不需要在单独的参数中将偏移值发送到内核,并在内核代码中使用该偏移量? 关于如何做到这一点的任何想法?

回答

6

指针算术在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呼叫已被施加到装置指针从所述第二字起始的副本,而不是首先。

+0

感谢您的回答。我知道这不是一个字节偏移量,但是,我不知道字的大小是多少。我只是简单地添加了我需要指针的索引号,就像我在C++中一样。那是对的吗? – pmcr 2011-05-06 10:02:42

+0

也许编辑会让事情变得更清晰一些? – talonmies 2011-05-06 10:12:52

+0

谢谢你的时间。这非常有帮助。现在正在工作。这是一个愚蠢的错误。我真的很抱歉。 – pmcr 2011-05-06 10:17:17

1

指针算术可以在主机端代码上工作,它在nvidia提供的示例代码中经常使用。 “

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

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

而且从性能基元(NPP)的文件,指针运算的一个很好的例子。

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

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

在C和C++中,指针运算可以按照上述方式或& ptr [offset](返回数据的设备内存地址而不是数值,该值不会在主机端代码的设备内存中)执行。使用任何一种符号时,数据类型的大小都会自动处理,并且偏移量被指定为多个数据元素而不是字节。