- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
[不是 Structure padding and packing 的拷贝| .这个问题是关于填充发生的方式和时间。这是关于如何处理它。]
我刚刚意识到 C++ 中的对齐会浪费多少内存。考虑以下简单示例:
struct X
{
int a;
double b;
int c;
};
int main()
{
cout << "sizeof(int) = " << sizeof(int) << '\n';
cout << "sizeof(double) = " << sizeof(double) << '\n';
cout << "2 * sizeof(int) + sizeof(double) = " << 2 * sizeof(int) + sizeof(double) << '\n';
cout << "but sizeof(X) = " << sizeof(X) << '\n';
}
使用 g++ 时,程序给出以下输出:
sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 24
那是 50% 的内存开销!在 134'217'728
X
的 3GB 数组中s 1 GB 将是纯填充。
double b
和
int c
大约:
struct X
{
int a;
int c;
double b;
};
现在结果更令人满意了:
sizeof(int) = 4
sizeof(double) = 8
2 * sizeof(int) + sizeof(double) = 16
but sizeof(X) = 16
但是有一个问题:这不是交叉兼容的。是的,在 g++ 下
int
是 4 个字节和一个
double
是 8 个字节,但这不一定总是正确的(它们的对齐也不必相同),因此在不同的环境下,此“修复”不仅无用,而且还可能通过增加需要的填充量。
struct
.也就是说,我不希望它的成员未对齐而因此访问速度较慢。相反,我仍然希望所有成员都是自对齐的,但在填充时使用最少的内存。这可以通过使用例如此处和
The Lost Art of Packing 中所述的手动重新排列来解决。通过埃里克雷蒙德。我正在寻找一种自动化的、尽可能多的跨平台方式来做到这一点,类似于
proposal P1112 中描述的内容对于即将到来的 C++20 标准。
最佳答案
(不要不假思索地应用这些规则。请参阅 ESR 关于您一起使用的成员的缓存位置的观点。并且在多线程程序中,要注意由不同线程编写的成员的错误共享。通常您不希望每个线程的数据在出于这个原因,根本就只有一个结构,除非你这样做是为了用大 alignas(128)
控制分隔。这适用于 atomic
和非原子变量;重要的是线程写入缓存行,而不管它们如何去做。)
经验法则:从大到小 alignof()
.没有任何事情可以做到在任何地方都是完美的,但到目前为止,最常见的情况是针对普通 32 位或 64 位 CPU 的理智的“普通”C++ 实现。所有原始类型都具有 2 的幂大小。
大多数类型都有alignof(T) = sizeof(T)
, 或 alignof(T)
以实现的寄存器宽度为上限。所以较大的类型通常比较小的类型更对齐。
大多数 ABI 中的结构打包规则为结构成员提供了绝对值 alignof(T)
相对于结构体的开头对齐,结构体本身继承最大的alignof()
其任何成员。
double
、 long long
和 int64_t
)。 ISO C++ 当然不会将这些类型修复为 64 位/8 字节,但实际上在您关心的所有 CPU 上都是如此。将您的代码移植到异国 CPU 的人员可以在必要时调整结构布局以进行优化。size_t
, intptr_t
, 和 ptrdiff_t
(可能是 32 位或 64 位)。对于具有扁平内存模型的 CPU,这些在普通现代 C++ 实现中的宽度都是相同的。long
(在 LLP64 ABI 中,例如 Windows x64,即使指针是 64 位,有时也是 32 位)。但它保证至少与 int
一样宽.int32_t
, int
, float
, enum
. (可选地将 int32_t
和 float
放在 int
之前,如果您关心仍将这些类型填充为 32 位的可能的 8/16 位系统,或者在它们自然对齐的情况下做得更好。大多数此类系统不会具有更宽的负载(FPU 或 SIMD),因此无论如何必须始终将更宽的类型作为多个单独的块进行处理)。int
窄至 16 位,或任意宽,但实际上即使在 64 位 CPU 上也是 32 位类型。 ABI 设计者发现设计用于 32 位的程序 int
如果 int
只是浪费内存(和缓存占用)更宽。不要做出会导致正确性问题的假设,但是对于“可移植性能”,您只需要在正常情况下是正确的。short
/int16_t
char
/int8_t
/bool
bool
标志,特别是如果主要是读取或者如果它们一起被修改,请考虑用 1 位位域打包它们。)int i
+
char buf[4]
将填充两个
double
之间的 8 字节对齐槽s。但这不是一个糟糕的假设,所以如果有某种原因(例如成员的空间局部性一起访问)将它们放在一起而不是最后,我还是会这样做。
alignof(long double) = 16
,但 i386 System V 只有
alignof(long double) = 4
,
sizeof(long double) = 12
.它是 x87 80 位类型,实际上是 10 个字节,但填充到 12 或 16 个字节,因此它是其 alignof 的倍数,从而在不违反对齐保证的情况下使数组成为可能。
sizeof(x) != alignof(x)
的聚合(结构或 union )时,它会变得更加棘手。 .
alignof(T)
double
仍然只有 4和
int64_t
.
alignof(T) = 4
对于大多数原始类型(但
malloc
仍然为您提供 8 字节对齐的内存,因为
alignof(maxalign_t) = 8
)。但无论如何,i386 System V 没有那个结构体打包规则,所以(如果你不从大到小排列你的结构体)你最终可能会得到 8 字节成员相对于结构体的开头未对齐.
[-128 .. +127]
),则可以节省代码大小。所以如果你有
任何类型的大数组,更喜欢稍后将它放在结构中 后经常使用的成员。即使这需要一些填充。
9. Readability and cache locality
While reordering by size is the simplest way to eliminate slop, it’s not necessarily the right thing. There are two more issues: readability and cache locality.
关于c++ - 如何在结构中组织成员以在对齐时浪费最少的空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56761591/
Webassembly:我找不到此语法的引用 (f32.const -0x0p+0) .它代表什么数字/位模式?它来自引用解释器的测试文件: https://github.com/WebAssembl
分析后,我发现我的程序有很大一部分内存被多重虚拟继承所浪费。 这是 MCVE 来演示问题 ( http://coliru.stacked-crooked.com/a/0509965bea19f8d9
如何在通过多个加载语句插入记录时避免跳过主 ID? 我通过 LOAD 语句将包含 150 条记录的文件插入到表中。 插入后表中最后一个primary id为150。 现在,当我通过加载语句插入另一个包
我开始了一份新工作,我正在工作的项目部分的结构非常奇怪。每个页面都是一个 .Net aspx 页面,并且加载得很好,但在加载时并没有真正执行任何操作。一切实际上都是从 jquery document.
我是一名优秀的程序员,十分优秀!