因为我一直在仔细考虑数据结构的对齐。在处理之前,可以让CPU进行混洗。除了强烈的感觉,我测量未对齐数据的成本:将64位长写入一些GB的内存,然后读取它们的值,检查正确性。
// c++ code
const long long MB = 1024 * 1024;
const long long GB = 1024 * MB;
void bench(int offset) // pass 0..7 for different alignments
{
int n = (1 * GB - 1024) / 8;
char* mem = (char*) malloc(1 * GB);
// benchmarked block
{
long long* p = (long long*) (mem + offset);
for (long i = 0; i < n; i++)
{
*p++ = i;
}
p = (long long*) (mem + offset);
for (long i = 0; i < n; i++)
{
if (*p++ != i) throw "wrong value";
}
}
free(mem);
}
结果让我感到惊讶:
1st run 2nd run %
i = 0 221 i = 0 217 100 %
i = 1 228 i = 1 227 105 %
i = 2 260 i = 2 228 105 %
i = 3 241 i = 3 228 105 %
i = 4 219 i = 4 215 99 %
i = 5 233 i = 5 228 105 %
i = 6 227 i = 6 229 106 %
i = 7 228 i = 7 228 105 %
成本仅为5%(如果我们将其随机存储在任何存储位置,成本将为3.75%,因为25%将对齐)。但是存储未对齐的数据具有更紧凑的优点,因此甚至可以补偿3.75%的收益。
测试在Intel 3770 CPU上运行。这个基准测试的许多变化(例如使用指针而不是long;随机读取访问来更改缓存效果)都会导致类似的结果。
问题:数据结构对齐是否仍然像我们所认为的那样重要?
我知道当64位值分布在缓存行上时存在原子性方面,但这对于对齐来说并不是一个强有力的论据,因为较大的数据结构(比如30,200字节左右)通常会在它们之间传播。
我总是非常相信速度论证,例如:Purpose of memory alignment,并且不要违背旧规则。但是:我们能否衡量所声称的正确对齐性能提升?
一个好的答案可以提供一个合理的基准,显示出因素的增加&gt; 1.25对齐对齐与未对齐数据。或者证明常用的其他现代CPU受到不对齐的影响更大。
感谢您的 ideas 测量。
编辑:我担心结构存储在内存中的经典数据结构。与科学数字运算场景等特殊情况相反。
更新:评论中的见解:
在Sandy Bridge上有效处理的未对齐的内存操作数
在Sandy Bridge上,读取或写入未对齐的内存操作数没有性能损失,除了它使用更多缓存库以便在操作数未对齐时缓存冲突的风险更高的事实。存储到 - 在大多数情况下,加载转发也适用于未对齐的操作数。
未对齐访问可能会在Sandy Bridge上更快(!)。
答案 0 :(得分:3)
是的,数据对齐是仅支持SSE(具有strict data alignment requirements)或更新架构(如Xeon PHI)的体系结构上矢量化的重要先决条件。英特尔AVX确实支持未对齐访问,但对齐数据仍被视为一种良好做法,to avoid unnecessary performance hits:
英特尔®AVX已经放宽了一些内存对齐要求,现在就这样了 默认情况下,Intel AVX允许未对齐访问;但是,这种访问可能 因为性能下降,所以设计数据的旧规则 内存对齐仍然是很好的做法(16字节对齐 128位访问和32字节对齐,用于256位访问)。主要的 例外是SSE指令的VEX扩展版本 明确要求内存对齐数据:这些指令仍然存在 需要对齐数据
在这些体系结构中,矢量化有用的代码(例如,大量使用浮点的科学计算应用程序)可以从满足各自的对齐先决条件中受益;加速比与FPU中的矢量通道数成正比(4,8,16X)。您可以通过比较Eigen或PetSC等软件或任何其他具有/不具有矢量化的科学软件(-xHost for icc
,-march = native for {{}来自行测量矢量化的好处。 1}}),你应该很容易获得2倍的加速。