我写了一个测试来说明我的问题,代码尝试将16个字节复制到非4字节对齐的内存,但 dest 会自动修改
#include <cuda.h>
#include <cuda_runtime.h>
#include <stdio.h>
__global__
void Copy128(char *dest,const char *src)
{
((int*)dest)[0]=((int*)src)[0];
((int*)dest)[1]=((int*)src)[1];
((int*)dest)[2]=((int*)src)[2];
((int*)dest)[3]=((int*)src)[3];
}
__global__
void fill_src(char *src)
{
for(int i=0; i<16; i++)
src[i] = i+1; // starts from 1
}
int main()
{
char* dest;
cudaMalloc(&dest, 17);
char* src;
cudaMalloc(&src, 16);
fill_src<<<1, 1>>>((char*)src); // fill some value for debugging
// copy to dest+1 which is not aligned to 4
Copy128<<<1, 1>>>(dest + 1, src);
getchar();
}
如图所示调试VS2013中的代码,目标内存为0x40A8000 1 ,但实际上它复制到0x40A8000 0 。
如果 dest 未与4字节对齐,则会自动修改 dest 。并且它被默默地修改,我花了几个小时来发现这个错误。
我知道最好使用良好对齐的内存,但我正在编写一些rar解压缩程序,解压缩一些字节然后连接一些字节,它不能总是对齐。
我想我会在像Copy256这样的函数中使用uint64。记忆是强制对齐的这种正常行为吗?任何可以关闭此功能的编译标志?或者我应该逐个复制字节?
环境:CUDA 6.5,Win7-32bit,VS2013
答案 0 :(得分:4)
- 内存强行对齐这是正常行为吗? 是:引自here,&#34;驻留在全局内存中或由驱动程序或运行时API中的一个内存分配例程返回的变量的任何地址始终对齐至少256个字节&#34;。
任何可以关闭此功能的编译标志? 我猜不是,这可能与硬件有关
或者我应该逐个复制字节吗? 如果您处理(非常)未对齐的内存,它是您避免错位存储的唯一选择(如上所述)。 但是,您应该尝试在内存操作对齐时检测(在编译时或运行时),然后使用您手头最宽的加载/存储(int4导致ldg指令,这将为您提供更好的带宽)