在Cache中加载时的数据对齐

时间:2017-05-04 07:13:01

标签: c++ c caching memory-alignment

假设4字节的自然对齐。

struct Node
{
int data;
char c_data;
};
int main() {
int global = 10;
struct Node N;
for ( register int i = 0; i < 10; i++)
cout << global << N.data << endl; }

如果缓存行大小为16字节,并且如果我的程序在循环中访问这两个变量,那么这些变量将如何出现在缓存中?假设其他一切都是寄存器变量。

在相同的缓存行上?

在不同的缓存行上?

如果相同的缓存行,每个成员是否会在缓存中以4字节对齐的地址开始?像全局变量将跨越[0,3]而N将跨越[4,7] ......类似的东西?或者,如果结构只有一个char,它甚至可以从高速缓存中的[5]开始。

基本上,在缓存中加载数据时,会根据结构的大小或它的第一个成员来考虑对齐吗?

1 个答案:

答案 0 :(得分:2)

如何使用缓存主要取决于代码,这是您在问题中提到但未发布的理论循环。循环之前使用的其他变量可能优先,具体取决于在哪里分配的变量。即使给出了一个特定系统的详细源代码,也很难确切地说明会发生什么。

在内存中相邻分配的变量是缓存友好的。基本上应该有一大块相邻分配的变量可以从RAM传输到缓存,以使缓存高效。如果你在完全不同的段中有变量,那么就会产生“缓存未命中”:也就是说,某些东西必须从缓存中抛出,而其他东西必须从RAM中读取。

例如,如果你有一大堆本地堆栈分配的变量,那么将它们全部存储在缓存中可能是有益的。

在您的情况下,global分配在内存的.data部分,N分配在.bss部分,因此它们根本不相邻并赢得由于这个原因,不会加载到同一个缓存行中。这意味着在您的情况下,整个缓存讨论甚至都不适用。

如果您改为编写struct Node N = {1};,那么假设变量(如果在代码中的相同位置使用)最终会在.data中以这样的方式分配似乎是合理的(我是疯狂推测):

4 bytes - global
4 bytes - N.data
4 bytes - N.c_data

调整对齐以适应CPU。缓存只是镜像RAM,没有任何东西“移动以适应对齐” - 当变量在RAM中分配时,已经考虑了对齐。

然后,这整个块可能会被一行读入缓存。