【问题标题】:Data Alignment while loading in Cache在缓存中加载时的数据对齐
【发布时间】:2017-05-04 07:13:01
【问题描述】:

假设自然对齐 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] 开始。

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

【问题讨论】:

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

标签: c++ c caching memory-alignment


【解决方案1】:

缓存的使用方式主要取决于代码,即您在问题中提到但未发布的理论循环。循环之前使用的其他变量可能优先,具体取决于分配在何处的变量。即使给出详细的源代码并考虑到特定的系统,也很难准确地说出会发生什么。

在内存中相邻分配的变量是缓存友好的。基本上应该有一大块相邻分配的变量可以从 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 中分配时,对齐已经被处理了。

然后这整个块可能会作为一个整体读入缓存。

【讨论】:

  • 根据您的回答,我修改了问题以将 global 和 N 作为局部变量。现在我的问题是,cachleline 上的 global 或 N 的地址是否将是 4 的倍数的偏移量?像 0,4,8 。或者它可以从缓存线上的偏移量 3 、 5 开始吗?可能是我在这里缺少架构知识。请指导如何从对齐的角度将数据拉入并存储在缓存中。
  • @AnupBuchke 如果编译器/链接器将它们放在 RAM 中对齐的地址开始,变量将被对齐。缓存只是 RAM 的一个相同副本,包含 0 到 n 个字节的数据。
  • 非常感谢。这有帮助。我将查找链接器如何将它们放入 RAM。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-31
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 1970-01-01
  • 2013-04-16
  • 1970-01-01
相关资源
最近更新 更多