在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 *?请有人解释一下这条线。看起来有点奇怪。
答案 0 :(得分:6)
这是由于pointer arithmetic在C中的工作方式。当您向指针x
添加整数p
时,它并不总是添加x
个字节。它增加了x
次sizeof([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个字节(*
)。