cpp和CUDA中结构的大小不同

时间:2019-03-23 20:38:53

标签: c++ cuda alignment eigen

使用内核时,我遇到了一些问题,该内核使用了我在c ++中定义的某些结构。错误cuda-memcheck给我的提示是对齐问题。

我要使用的结构包含一些指针,我认为这给了我一些问题。我已经在.cu文件和内核中的主机函数中打印了C ++端和CUDA端的结构大小控制台。这给出了不同的结果,解释了我所遇到的问题,但是我不确定为什么会发生,也不确定如何解决。

我正在使用的结构如下

struct Node {};
struct S
{
    Node *node0;
    Node *node1;
    Node *node2;
    double p0;
    double p1;
    double p2;
    double p3;

    Eigen::Matrix<double, 3, 2> f1;
    Eigen::Matrix<double, 3, 2> f2;
}

在C ++中,它的大小为160字节,在CUDA中为152字节。要传输数据,我要分配一个CUDA侧缓冲区并执行cudaMemcpy

std::vector<S> someVector; // Consider it exists
S *ptr;
cudaMalloc(&ptr, sizeof(S) * someVector.size());
cudaMemcpy(ptr, someVector.data(), sizeof(S)*someVector.size(), cudaMemcpyHostToDevice);

我猜错了,因为CUDA和C ++中的大小不同。

当我尝试访问内核中的S::node0S::node1S::node3时,我收到一个未对齐的访问错误。

所以我对此问题有三个疑问:

  • 为什么尺寸不同?
  • 如何更改代码或执行复制以使其正常工作?
  • 我应该具有CUDA侧结构并执行特殊复制吗?

编辑: 多亏了被接受的答案,我才能够了解出现此问题的原因。 Eigen在可能的情况下使用矢量化,并为此请求16字节对齐。当本征对象大小是16字节的倍数时,启用矢量化。在我的特定情况下,两个Eigen::Matrix<double, 3,2>对于矢量化有效。

但是,在CUDA中,Eigen不要求16字节对齐。

由于我的结构具有4个双精度和3个指针,该指针计数为56个字节,而不是16的倍数,因此在CPU中它必须添加8个填充字节,因此本征矩阵为16字节对齐。在CUDA中不会发生这种情况,因此大小会有所不同。

我实现的解决方案是手动添加8个填充字节,因此CPU和CUDA中的结构相同。这解决了问题,不需要禁用向量化。我发现可以使用的另一种解决方案是将Eigen::Matrix<double,3,2>更改为2 Eigen::Matrix<double,3,1>Eigen::Matrix<double,3,1>不满足向量化的要求,因此不需要在CPU中添加8个填充字节。

1 个答案:

答案 0 :(得分:1)

这种差异是由于Eigen在C ++和CUDA中请求内存对齐的方式。

在C ++中,S被对齐为16个字节(您可以检查alignof(S) == 16)。这是由于Eigen的矩阵对齐到16个字节,可能是由于使用了需要这种对齐的SSE寄存器。您其余的字段对齐为8字节(64位指针和双精度)。

Eigen/Core头文件EIGEN_DONT_VECTORIZE指令中为CUDA启用了。检查documentation时:

  

EIGEN_DONT_VECTORIZE-定义后禁用显式矢量化。默认情况下未定义,除非通过Eigen的平台测试或用户定义EIGEN_DONT_ALIGN禁用对齐。

基本上意味着Eigen矩阵在CUDA中没有特殊的对齐方式,因此它们与元素类型double对齐(在您的情况下),从而导致矩阵以及整个结构的8字节对齐。

解决此问题的最佳方法是强制两种结构的结构对齐。目前在CUDA中不太熟练,我认为您可以在CUDA中使用__align__(16)(更多here),并在C ++中使用alignas(16)since C++11)来做到这一点。如果您同时共享两种语言的声明,则可以定义宏以使用正确的运算符:

#ifdef __CUDACC__
# define MY_ALIGN(x) __align__(x)
#else
# define MY_ALIGN(x) alignas(x)
#endif

struct MY_ALIGN(16) S {
  // ...
};

无论如何,请注意这样的低级副本,因为Eigen在CUDA中的实现可能与C ++中的实现不同(Eigen的文档中对此没有保证)。