c++ - 加载到缓存时数据对齐

标签 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] 开始......类似的东西?或者,如果结构只有一个字符,它甚至可以从缓存行中的 [5] 开始。

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

最佳答案

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

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

这整个 block 可能会作为一个整体读入缓存。

关于c++ - 加载到缓存时数据对齐,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43776218/

相关文章:

c - 做 while 和右移没有效果

c++ - golangatomic.Load 有获取语义吗?

c++ - 使用 protected 方法而不是为继承树中的每个派生类创建新的虚函数是一种好习惯吗?例如。在描述中

c++ - _splitpath_s : wrong argument type?

c - IPv6 组播接口(interface)选择

caching - 使用 Entity Framework 5 缓存查询

c++ - 提示错误时的 emplace_hint 性能

c++ - 从包含伪装成随机字符 C++ 的二进制数的文件中读取?

laravel - Lumen PHP Artisan配置:cache not found

php - WooCommerce: header 中的迷你购物车似乎已缓存