- 内存对齐
在CPU端为了加速和防止内存碎片往往会写个简单的内存池,就是个char**类型的二维数组,每个char对应一段内存,需要多少就把下标记录下来,用的时候把char强转成所需要的对应的结构指针。
在GPU上这个方法需要注意一下内存对齐。char是没有对齐的,如果申请一个点类型的空间,cuda会自动按4字节对齐,如下
struct point{
float x;
float y;
float z;
}
这个时候把char* 转成point* 就会报错CUDA error: misaligned address
所以这里需要把char**换成int ** ,然后把point按 4 字节对齐,如下:
#if defined(__CUDACC__) // NVCC
#define MY_ALIGN(n) __align__(n)
#elif defined(__GNUC__) // GCC
#define MY_ALIGN(n) __attribute__((aligned(n)))
#elif defined(_MSC_VER) // MSVC
#define MY_ALIGN(n) __declspec(align(n))
#else
#error "Please provide a definition for MY_ALIGN macro for your host compiler!"
#endif
struct MY_ALIGN(4) point{
float x;
float y;
float z;
}
- block之间的数据同步
这个问题老生常谈了,不同的block同时读写一个变量只用__threadfence()经我测试是不够的,一定要用原子操作atomicAdd,atomicExch等,读取可以用atomicMax,例如一个unsigned int num这种不小于0的变量,使用atomicMax(&num, 0)会返回num的同步真实值。 - 最后一点就是不要用cudaMallocManaged,会有极低的概率出现页错误,特别坑。