将float*转换为char*,同时在设备上的线性内存中循环2-D数组

smi*_*dha 4 c++ pointers cuda

在CUDA 4.0编程指南的第21页上,有一个示例(如下所示)来说明在设备存储器中循环2D浮点数组的元素.2D的尺寸是宽度*高度

// Host code
int width = 64, height = 64;
float* devPtr;
size_t pitch;
cudaMallocPitch(&devPtr, &pitch,
width * sizeof(float), height);
MyKernel<<<100, 512>>>(devPtr, pitch, width, height);


// Device code
__global__ void MyKernel(float* devPtr, size_t pitch, int width, int height)
{
   for (int r = 0; r < height; ++r) 
    {
       float* row = (float*)((char*)devPtr + r * pitch);
          for (int c = 0; c < width; ++c) 
              {
              float element = row[c];
              }
     }
}
Run Code Online (Sandbox Code Playgroud)

为什么devPtr设备内存指针被强制转换为全局内核函数中的字符指针char*?请有人解释一下这条线.看起来有点奇怪.

Jon*_*art 6

这是由于指针算法在C中的工作方式.当您x向指针添加整数时p,它并不总是添加x字节.它增加了x时间sizeof([type that p points to]).

float* row = (float*)((char*)devPtr + r * pitch);
Run Code Online (Sandbox Code Playgroud)

通过强制转换devPtr为a char*,applied(r * pitch*)的偏移量为1字节增量.(因为a char是一个字节).如果没有进行转换,则应用于devPtr的偏移量将是r * pitch 4个字节,因为a float是4个字节.

例如,如果我们有:

float* devPtr = 1000;
int r = 4;
Run Code Online (Sandbox Code Playgroud)

现在,让我们省略演员:

float* result1 = (devPtr + r);
// result1 = devPtr + (r * sizeof(float)) = 1016;
Run Code Online (Sandbox Code Playgroud)

现在,如果我们包括演员:

float* result2 = (float*)((char*)devPtr + r);
// result2 = devPtr + (r * sizeof(char)) = 1004;
Run Code Online (Sandbox Code Playgroud)