cuda内存对齐

标签 cuda

在我的代码中,我使用结构来促进将参数传递给函数(我不使用结构数组,而是一般使用数组结构)。 当我在 cuda-gdb 中时,我检查内核中的点,在该点上我给一个简单的结构赋值,例如

struct pt{
int i;
int j;
int k;
}

尽管我没有做一些复杂的事情,而且很明显成员应该指定值(value)观,但我明白......

Asked for position 0 of stack, stack only has 0 elements on it.

所以我在想,即使它不是一个数组,也许当时的内存对齐有问题。所以我将头文件中的定义更改为

struct __align__(16) pt{
int i;
int j;
int k;
}

但是,当编译器尝试编译使用相同定义的主机代码文件时,会出现以下错误:

error: expected unqualified-id before numeric constant error: expected ‘)’ before numeric constant error: expected constructor, destructor, or type conversion before ‘;’ token

那么,我应该对主机和设备结构有两种不同的定义吗???

此外我想问一下如何概括对齐的逻辑。我不是计算机科学家,因此编程指南中的两个示例并不能帮助我了解全局。

比如下面两个应该如何对齐?或者,具有 6 个 float 的结构应该如何对齐?还是4个整数?再说一遍,我没有使用这些数组,但我仍然在内核或 _ device _ 函数中使用这些结构定义了很多变量。

struct {
    int a;
    int b;
    int c;
    int d;
    float* el;    
} ;

 struct {
    int a;
    int b
    int c
    int d
    float* i;
    float* j;
    float* k;
} ;

提前感谢您的任何建议或提示

最佳答案

这篇文章有很多问题。由于 CUDA 编程指南在解释 CUDA 中的对齐方面做得非常好,因此我将只解释指南中不明显的一些内容。

首先,主机编译器给你错误的原因是主机编译器不知道 __align(n)__ 是什么。意味着,所以它给出了语法错误。您需要的是将如下内容放入项目的 header 中。

#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

So, am I supposed to have two different definitions for host and device structures?

不,只需使用 MY_ALIGN(n) ,像这样

struct MY_ALIGN(16) pt { int i, j, k; }

For example, how should the following two be aligned?

首先,__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 字节)完全消除浪费,但这会导致过多的负载。再次强调权衡。

or, how should a structure with 6 floats be aligned?

再次权衡:要么每个结构浪费 8 个字节,要么每个结构需要两次加载。

or 4 integers?

这里没有权衡。 MY_ALIGN(16) .

again, I'm not using arrays of those, but still I define lots of variables with these structures within the kernels or _ device _ functions.

嗯,如果您不使用这些数组,那么您可能根本不需要对齐。但你如何分配给他们呢?正如您可能看到的,所有这些浪费都是值得担心的——这是支持数组结构而不是结构数组的另一个很好的理由。

关于cuda内存对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12778949/

相关文章:

c++ - 如何在 .cpp 文件中使用 Cuda 数据结构

cuda - NVidia的ISA语言

cuda - 如何最好地将大量字符数组传输到 GPU?

c++ - CUDA 语法错误 '<'

c++ - 如何分配指针数组并为cuda中的多个内核调用保留它们

cuda - 如何在 visual studio 2010 中更改 compute _' ' 和 sm _' ' 参数?

java - 尝试使用 Cuda 运行 Nd4j 时出错

cuda - Mathematica 中 NVIDIA K20 GPU 上的内核数

cuda - __CUDA_ARCH__ 宏的行为

内核 CUDA 中的 C++ 代码?