【发布时间】:2011-07-12 06:53:36
【问题描述】:
我想计算/总结由于打包导致的目标文件中的开销(理想情况下,让 gcc 为我将其最小化)。
例如,考虑以下结构(32 位 x86,gcc):
struct a {
uint8_t a_char;
uint32_t an_integer
uint8_t another_letter;
};
虽然实际数据只占用 6 个字节,但该结构在内存中占用 12 个字节,因为两个字符后面都跟着 3 个填充字节。通过重新排序结构如下:
struct b {
uint32_t an_integer
uint8_t a_char;
uint8_t another_letter;
};
该结构将只有 sizeof(struct b) == 8(仍然是 4 个字节的开销)。
(1) 理想情况下,我希望 gcc 将 struct a 重新排列为 struct b 并节省空间,但我的版本 (4.2) 似乎没有针对任何优化级别执行此操作。
(2) 或者,给定struct a,我想(自动)获得数字6(总开销)或4(最小开销,如果成员按“理想情况下”排序”)。这样做的目的是确定手动重新排序结构是否值得花时间(可能不值得)。
gcc 有没有办法执行 (1),是否有工具可以执行 (2)?对于(1),我能想到的最接近的事情是#pragma pack(1),但是(我猜)它会通过使大多数/所有内存访问不对齐而对性能产生严重影响。对于(2),我认为解析调试符号的 Perl 脚本可能能够做到这一点,但我对 DWARF 不够熟悉,无法确定。
【问题讨论】:
-
AFAIK 未对齐内存访问与对齐访问一样快;只是编译器没有对它们进行一些优化。
-
未对齐的内存访问会导致
SIGBUS具有 4 或 8 字节类型 - 它们很重要。 -
@Mehrdad:某些架构对未对齐的内存访问零容忍,并且在发生这种情况时会抛出硬件异常。在这种情况下,操作系统会拦截它们并在软件中模拟未对齐的内存访问,这比对齐的访问要慢得多。即使在 x86 等“未对齐访问容忍”架构上,未对齐访问也较慢,并且某些指令(例如 SIMD)具有严格的对齐要求。
-
@Mehrdad,在 x86 上 is 尽管是相同的指令,但对齐与未对齐的性能差异(这取决于您的代码)。 CPU 只是有更多的工作要做——尤其是当您跨越缓存线边界时。更重要的是,关于原子性的某些保证仅适用于对齐值。
-
真的,有多难?一个天真的解决方案是只编写所有结构,其元素按尺寸递减排序......您实际上并不需要工具来为您执行此操作。
标签: c++ c gcc alignment packing