Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C(gcc/g+;+;)中的包装导致的计算开销_C++_C_Gcc_Alignment_Packing - Fatal编程技术网

C++ C(gcc/g+;+;)中的包装导致的计算开销

C++ C(gcc/g+;+;)中的包装导致的计算开销,c++,c,gcc,alignment,packing,C++,C,Gcc,Alignment,Packing,我想计算/总结对象文件中由于打包而产生的开销(理想情况下,让gcc为我最小化它) 例如,考虑下面的结构(32位x86,GCC): 虽然实际数据只占用6个字节,但该结构在内存中占用12个字节,因为两个字符后面都有3个填充字节。通过如下方式重新排列结构: struct b { uint32_t an_integer uint8_t a_char; uint8_t another_letter; }; 该结构的sizeof(struct b)==8(仍然有4字节的开销) (

我想计算/总结对象文件中由于打包而产生的开销(理想情况下,让gcc为我最小化它)

例如,考虑下面的结构(32位x86,GCC):

虽然实际数据只占用6个字节,但该结构在内存中占用12个字节,因为两个字符后面都有3个填充字节。通过如下方式重新排列结构:

struct b { 
    uint32_t an_integer
    uint8_t a_char;
    uint8_t another_letter;
};
该结构的sizeof(struct b)==8(仍然有4字节的开销)

(1) 理想情况下,我希望gcc将结构a重新排列为结构b,并节省空间,但我的版本(4.2)似乎没有在任何优化级别上做到这一点

(2) 或者,给定
struct a
,我想(自动)获得数字
6
(开销总量)或
4
(开销最小,如果成员是“理想”排序的)。其目的是确定手动重新排序结构是否值得花费时间(可能不值得)


gcc有没有办法做到(1),有没有可以执行(2)的工具?对于(1)我能想到的最接近的事情是
#pragma pack(1)
,但是(我猜)它会使大多数/所有内存访问不对齐,从而严重影响性能。对于(2),我认为Perl脚本解析调试符号可能可以做到这一点,但我对DWARF还不太熟悉,无法确定。这不可能总是做到。问题是,在所有体系结构上都不允许访问未对齐的内存。这也简化了编译器的一些代码,允许优化对内存本身的某些访问。此外,重新组织结构可能不值得花时间,因为每个结构4-8字节的开销不是什么大问题,除非您运行的是非常内存敏感的软件。至于你的问题,我不确定是否有办法,但我确信如果有人知道他们会让你知道(也许GCC-4.6有最高的优化标志,它)?< /P> < P> > 1,原因是C和C++标准都禁止结构成员重新排序。 是的,结构打包通常会降低性能。而且,正如在评论中提到的,在某些情况下,在非x86体系结构上,如果您尝试在成员上操作,您可以得到一个SIGBUS


对于#2,是的,perl脚本可能能够做到这一点。您可以尝试扫描源代码中的结构定义,或者生成一些小测试程序来检查sizeof()而不是解析DWARF信息结构和成员等等。

在linux中,有一个名为pahole的工具,它将解析带有调试信息的ELF文件,并为每个结构打印输出每个成员的对齐方式以及编译器完成的填充量。如果注意到开销过大,您可以使用该信息指导您手动打包。

AFAIK未对齐内存访问与对齐访问一样快;只是编译器没有对它们执行一些优化。未对齐的内存访问可能会导致4字节或8字节类型的SIGBUS,它们很重要。@Mehrdad:某些体系结构对未对齐的内存访问没有容忍度,在这种情况下会引发硬件异常。在这种情况下,操作系统会拦截它们,并在软件中模拟未对齐的内存访问,这比对齐的访问慢得多。即使在“未对齐的访问容忍”体系结构(如x86)上,未对齐的访问速度也较慢,而且某些指令(如SIMD)具有严格的对齐要求。@Mehrdad,在x86上,尽管是同一条指令,对齐与未对齐的性能仍存在差异(这取决于您的代码)。CPU只是有更多的工作要做——特别是当您跨越缓存线边界时。更重要的是,关于原子性的某些保证只适用于对齐的值。真的,这有多难?一个简单的解决方案是,只需编写所有结构,并将其元素按递减的大小排序。。。你真的不需要工具来帮你做这件事。1-你说得对,我找到了。“在结构对象中,非位字段成员和位字段所在的单元的地址按声明顺序递增。”——。唉。谢谢。可以补充的是,即使它可以重新排序,也可能没有帮助,因为它必须确保每个成员在放置到阵列中时仍必须满足对齐要求,另一个要考虑的性能问题是,在某些情况下,重新排序结构元素可能会导致一个不太有利的高速缓存/内存访问模式,甚至更糟的性能,即使总的内存消耗更少。
struct b { 
    uint32_t an_integer
    uint8_t a_char;
    uint8_t another_letter;
};