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

时间:2012-01-07 18:55:25

标签: c++ pointers cuda

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

// 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];
              }
     }
}

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

3 个答案:

答案 0 :(得分:6)

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

float* row = (float*)((char*)devPtr + r * pitch);

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

例如,如果我们有:

float* devPtr = 1000;
int r = 4;

现在,让我们省略演员阵容:

float* result1 = (devPtr + r);
// result1 = devPtr + (r * sizeof(float)) = 1016;

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

float* result2 = (float*)((char*)devPtr + r);
// result2 = devPtr + (r * sizeof(char)) = 1004;

答案 1 :(得分:1)

强制转换只是为了使指针算术工作正确;

(float*)((char*)devPtr + r * pitch);

时向前移动r *音高字节
(float*)(devPtr + r * pitch);

将向前移动r * pitch float(即4倍的字节数)

答案 2 :(得分:0)

*(devPtr + 1)取消引用之前,

sizeof(float)会将指针偏移4个字节(*)。 在*((char)devPtr + 1)取消引用它之前,sizeof(char)会将指针偏移1个字节(*)。