技术开发 频道

CUDA 结构对齐的C++模拟

  【IT168 文档】CUDA的nvcc编译器支持数据结构struct的对齐,以此来提高速度。但当我们想从C++里创建数据结构,然后传到GPU里,用GPU处理的时候,我们就必须注意这个对齐了,怎么在C++里模拟CUDA的对齐呢?今天我发现,其实,结构的内存对齐并不是nvcc的魔法,nvcc其实也只是使用了C++的对齐机制。但为什么要多出一个__align__关键字呢?原来,C++的结构对齐并不是一个跨平台的标准,所以nvcc用__align__来统一。

  为了找到模拟的方法,我分别在Windows和Linux下搜索nvcc的中间输出文件(xxx.cpp1.ii文件,其中xxx是你的cu文件的文件名),找到了使用的C++关键字,于是我定义如下宏,来在C++中模拟CUDA的对齐机制:

#if defined (__CUDACC__)
#define ALIGN16         __align__(
16)
#elif defined (__GCCXML__)
#define ALIGN16
#elif defined (_MSC_VER)
#define ALIGN16         __declspec(align(
16))
#elif defined (__GNUC__)
#define ALIGN16         __attribute__((__aligned__(
16)))
#
else
#error compiler unsupport
for alignment
#endif

  在测试的时候,我还发现一个有趣的现象,Windows和Linux对0大小的结构,其sizeof结果不尽相同。

  假设我们有个模板:

template <unsigned int len, typename value_type>
struct ALIGN16 foo
{
    value_type x[len];
};

  然后我们用测试程序输出其sizeof结果:

  首先是Windows下的输出:

sizeof(foo <0, float>) = 16
sizeof(foo
<1, float>) = 16
sizeof(foo
<2, float>) = 16
sizeof(foo
<3, float>) = 16
sizeof(foo
<4, float>) = 16
sizeof(foo
<5, float>) = 32
sizeof(foo
<6, float>) = 32
sizeof(foo
<7, float>) = 32
sizeof(foo
<8, float>) = 32

  而Linux下的输出:

sizeof(foo <0, float>) = 0
sizeof(foo
<1, float>) = 16
sizeof(foo
<2, float>) = 16
sizeof(foo
<3, float>) = 16
sizeof(foo
<4, float>) = 16
sizeof(foo
<5, float>) = 32
sizeof(foo
<6, float>) = 32
sizeof(foo
<7, float>) = 32
sizeof(foo
<8, float>) = 32

  不同之处在于foo<0, float>,因为对于struct foo { char a[0]; }, 其sizeof在Windows下是1,如果我们对齐到16,则是16;而在Linux下,其sizeof是0,对齐到16则是0。

0
相关文章