为什么gcc和NVCC(g ++)看到两种不同的结构尺寸?

Mik*_*ail 6 c c++ gcc cuda nvcc

我正在尝试将CUDA添加到90年代末期编写的现有单线程C程序中.

为此,我需要混合两种语言,C和C++(nvcc是一个c ++编译器).

问题是C++编译器将结构看作某个大小,而C编译看到的结构与稍微不同的大小相同.那很糟.我真的很困惑,因为我找不到4字节差异的原因.

/usr/lib/gcc/i586-suse-linux/4.3/../../../../i586-suse-linux/bin/ld: Warning: size of symbol `tree' changed from 324 in /tmp/ccvx8fpJ.o to 328 in gpu.o
Run Code Online (Sandbox Code Playgroud)

我的C++看起来像

#include <stdio.h>
#include <stdlib.h>
#include "assert.h"
extern "C"
{
#include "structInfo.h" //contains the structure declaration
}
...
Run Code Online (Sandbox Code Playgroud)

和我的C文件看起来像

#include "structInfo.h"
...
Run Code Online (Sandbox Code Playgroud)

与structInfo.h看起来像

struct TB {
   int  nbranch, nnode, root, branches[NBRANCH][2];
         double lnL;
}  tree;
...
Run Code Online (Sandbox Code Playgroud)

我的make文件看起来像

PRGS =  prog
CC = cc
CFLAGS=-std=gnu99 -m32
CuCC = nvcc
CuFlags =-arch=sm_20
LIBS = -lm -L/usr/local/cuda-5.0/lib -lcuda -lcudart
all : $(PRGS)
prog: 
        $(CC) $(CFLAGS) prog.c gpu.o $(LIBS) -o prog
gpu.o:
        $(CuCC) $(CuFlags) -c gpu.cu
Run Code Online (Sandbox Code Playgroud)

有些人问我为什么不使用不同的主机编译选项.我认为主机编译选项自2发布以来已被弃用?也一直没有出现做什么它说,它会做.

nvcc warning : option 'host-compilation' has been deprecated and is ignored
Run Code Online (Sandbox Code Playgroud)

nju*_*ffa 16

GPU需要对所有数据进行自然对齐,例如,4字节的int需要与4字节边界对齐,8字节的double或long long需要具有8字节的对齐.CUDA也对主机代码强制执行此操作,以确保结构在代码的主机和设备部分之间尽可能兼容.另一方面,x86 CPU通常不需要数据自然对齐(尽管性能损失可能是由于缺少对齐).

在这种情况下,CUDA需要将结构的double组件与8字节边界对齐.由于奇数个int组件在double之前,因此需要填充.切换组件的顺序,即将双组件放在第一位,没有用,因为在这种结构的数组中,每个结构必须是8字节对齐的,因此结构的大小必须是8字节的倍数才能实现,这也需要填充.

要强制gcc以与CUDA相同的方式对齐双打,请传递标记-malign-double.


Som*_*ame 5

看起来像2个编译器应用的不同填充:一个使用4字节对齐,另一个使用至少8字节对齐.您应该能够通过编译器特定的#pragma指令强制执行所需的对齐(请查看有关特定的编译器文档#pragma).

  • 我认为你需要的gcc是编译器标志-malign-double.由于GPU需要对所有数据进行自然对齐,因此CUDA也会在主机上强制执行此操作,以确保结构在代码的主机和设备部分之间兼容.由于结构中double前面的整数是奇数,因此需要填充结构.或者,您可以重新排序结构的组件,因此double是第一个组件. (5认同)