这个帖子有很多问题。由于 CUDA 编程指南在解释 CUDA 中的对齐方面做得很好,我将仅解释一些在指南中不明显的内容。
首先,你的主机编译器给你错误的原因是因为主机编译器不知道是什么__align(n)__意思,所以它给出了一个语法错误。您需要在项目的标题中添加以下内容。
#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
那么,我应该对主机和设备结构有两种不同的定义吗?
不,只需使用MY_ALIGN(n),就像这样
struct MY_ALIGN(16) pt { int i, j, k; }
比如下面这两个应该怎么对齐?
首先,__align(n)__(或任何主机编译器风格),强制结构的内存开始于内存中多个n字节的地址。如果结构的大小不是 的倍数n,则在这些结构的数组中,将插入填充以确保每个结构正确对齐。要为 选择适当的值n,您希望最小化所需的填充量。如编程指南中所述,硬件要求每个线程读取与 1、2、4、8 或 16 字节对齐的字。所以...
struct MY_ALIGN(16) {
int a;
int b;
int c;
int d;
float* el;
};
在这种情况下,假设我们选择 16 字节对齐。在 32 位机器上,指针占用 4 个字节,因此结构占用 20 个字节。16 字节对齐会浪费16 * (ceil(20/16) - 1) = 12每个结构的字节数。在 64 位机器上,由于 8 字节指针,每个结构只会浪费 8 个字节。我们可以通过使用MY_ALIGN(8)来减少浪费。权衡是硬件将不得不使用 3 个 8 字节加载而不是 2 个 16 字节加载来从内存加载结构。如果您没有受到负载的限制,这可能是一个值得权衡的选择。请注意,您不想为此结构对齐小于 4 个字节。
struct MY_ALIGN(16) {
int a;
int b
int c
int d
float* i;
float* j;
float* k;
};
在这种 16 字节对齐的情况下,在 32 位机器上每个结构仅浪费 4 个字节,在 64 位机器上浪费 8 个字节。它需要两个 16 字节的加载(或 64 位机器上的 3 个)。如果我们对齐到 8 个字节,我们可以通过 4 字节对齐(在 64 位机器上为 8 个字节)完全消除浪费,但这会导致负载过大。再次,权衡。
或者,应该如何对齐具有 6 个浮点数的结构?
同样,权衡:每个结构浪费 8 个字节或每个结构需要两次加载。
还是4个整数?
这里没有权衡。MY_ALIGN(16).
同样,我没有使用这些数组,但我仍然在内核或_设备_函数中使用这些结构定义了许多变量。
嗯,如果您不使用这些数组,那么您可能根本不需要对齐。但是你是如何分配给他们的?正如您可能看到的那样,所有这些浪费都是值得担心的——这是另一个支持数组结构而不是结构数组的好理由。