2017-05-04 75 views
2

假定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字节,如果我的程序在访问这些环2个变量,这些变量将如何存在于缓存?假设一切都是寄存器变量。

在同一缓存行?

在不同的缓存行?

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

基本上,在将数据加载到缓存中时,根据结构的大小考虑对齐还是第一个成员?

+0

根据行大小而不是数据大小将数据加载到缓存行中,因此,内存中的数据组织/对齐会反映到缓存中。 – LPs

回答

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中时,对齐将已经被处理。

这整个块可能会作为一个潜在的读入缓存。

+0

根据你的回答,我修改了问题以保持全局和N为局部变量。现在我的问题是,无论是全球的还是N的地址都是4的倍数的偏移量?如0,4,8。或者它可以从缓存行的偏移量3,5开始?可能是我在这里缺少建筑知识。请从对齐的角度指导如何将数据拉入并存储在缓存中。 –

+1

@AnupBuchke如果编译器/链接器将它们放在RAM中对齐的地址上,变量将会对齐。缓存只是RAM的相同副本,包含0到_n_字节的数据。 – Lundin

+0

非常感谢。这有帮助。我将查找链接器如何将它们放入RAM中。 –