CUDA C++中为何将设备指针转为char*而非直接以float*递增?
核心原因是cudaMallocPitch返回的pitch是每行占用的字节数,而非float元素的个数,必须用基于字节的指针算术才能准确定位行地址,具体拆解如下:
pitch的单位是字节cudaMallocPitch会为了GPU内存访问的对齐要求,分配比实际行数据更大的内存空间,返回的pitch就是每行实际占用的总字节数(包含对齐填充的额外字节)。比如你申请64个float(共256字节),pitch可能等于256字节,也可能是更大的对齐值(比如512字节,取决于设备硬件要求)。指针算术的规则差异
C++中,指针加减会根据类型自动缩放步长:float*类型的指针,ptr + 1会偏移4字节(一个float的大小);而char*类型的指针,ptr + 1只偏移1字节,刚好对应单个字节的位移。
如果直接用float* devPtr + r * pitch,编译器会把r * pitch当成float元素的个数,实际偏移量变成r * pitch * sizeof(float)字节,这和pitch本身是字节数的定义完全矛盾,会直接定位到错误的内存地址。
转成char*后,(char*)devPtr + r * pitch就是准确的字节偏移,刚好对应第r行的起始地址,再转回float*就能正常访问该行元素。实际例子验证
假设pitch是256字节(刚好等于64个float的大小),用char*计算时,第1行起始地址是devPtr + 256字节,完全正确;如果用float*直接计算,会变成devPtr + 256个float,也就是偏移256*4=1024字节,直接跳到了第4行的位置,明显错误。
内容的提问来源于stack exchange,提问作者tearis

