C++ “a”的价格是多少;“大的”;对象被带进缓存?
如果我有一个包含多个大向量的对象,如果我访问其中一个向量数据成员,是否意味着其他向量(我没有访问)也会被带到缓存中(可能是根据代码的空间局部性规则) 如果我有:C++ “a”的价格是多少;“大的”;对象被带进缓存?,c++,performance,caching,cpu,cpu-architecture,C++,Performance,Caching,Cpu,Cpu Architecture,如果我有一个包含多个大向量的对象,如果我访问其中一个向量数据成员,是否意味着其他向量(我没有访问)也会被带到缓存中(可能是根据代码的空间局部性规则) 如果我有: class A{ float p; int x[10000]; int y[10000]; }; 我只访问了一段特定代码中的p,访问a::p会不会比 class B{ float p; int x[10000]; double y; }; 因为B更小,因为只有一个大数组 我的直觉是,只
class A{
float p;
int x[10000];
int y[10000];
};
我只访问了一段特定代码中的p
,访问a::p
会不会比
class B{
float p;
int x[10000];
double y;
};
因为B
更小,因为只有一个大数组
我的直觉是,只加载频繁访问的缓存线,而不是整个对象。与您从中读取的地址相对应的缓存线被加载,而与对象无关 这取决于你的平台。对于64字节(8或16个整数)的缓存线,根据对齐方式,读取
x[0…15]
中的任何一个都只会导致在缓存中加载这些元素
读取元素x[16]
将把它和后续元素加载到不同的缓存线中
根据缓存的总大小,读取(例如
x[9000]
)可能会导致缓存冲突,并且先前填充的行将被清除,以便为新元素腾出空间。与读取的地址相对应的缓存行将被加载,而与对象无关
这取决于你的平台。对于64字节(8或16个整数)的缓存线,根据对齐方式,读取x[0…15]
中的任何一个都只会导致在缓存中加载这些元素
读取元素x[16]
将把它和后续元素加载到不同的缓存线中
根据缓存的总大小,读取(例如
x[9000]
)可能会导致缓存冲突,并且先前填充的行将被清除,以便为新元素腾出空间。机器对类的布局一无所知,因此类大小无关。它只知道您实际访问的内存,即您的访问模式。一旦代码被编译,类的布局信息甚至可能不存在于内存中,因此机器无法计算出来。机器对类的布局一无所知,因此类的大小无关紧要。它只知道您实际访问的内存,即您的访问模式。一旦代码被编译,类的布局信息甚至可能不存在于内存中,因此机器无法计算出来。正如在其他答案中提到的,内存子系统不知道对象的内存布局。它只看到对相应地址的内存访问。因此,无论对象有多大,都会将相同数量的数据加载到缓存中
至于加载多少数据的问题,这取决于体系结构。在简单系统上,仅加载相应的缓存线。另一方面,现代x86CPU也有预取机制。此机制尝试确定下一步最可能需要的内存地址,并提前获取这些缓存线。这就是为什么顺序存取比随机存取快得多(数量级)的原因,因为在这里,预取程序总是选择正确的数据
编辑:
但同样:这与类的大小无关,只取决于访问模式(当然可能取决于类的内存布局)。正如其他答案中提到的,内存子系统不知道对象的内存布局。它只看到对相应地址的内存访问。因此,无论对象有多大,都会将相同数量的数据加载到缓存中 至于加载多少数据的问题,这取决于体系结构。在简单系统上,仅加载相应的缓存线。另一方面,现代x86CPU也有预取机制。此机制尝试确定下一步最可能需要的内存地址,并提前获取这些缓存线。这就是为什么顺序存取比随机存取快得多(数量级)的原因,因为在这里,预取程序总是选择正确的数据 编辑:
但同样:这与类的大小无关,只取决于访问模式(当然可能取决于类的内存布局)。缓存行为取决于机器。如果加载一块内存,周围的内存可能也会被缓存,但缓存的内存大小与结构的外观无关,因为您的计算机不知道结构是什么,也不关心您是否认为其成员属于同一个结构。缓存线的大小是一定的,可能是128字节。如果必须访问该行中的任何字节,则会引入整行(甚至是不相关对象中的字节)。在最简单的缓存方案中,在引用它们之前不会引入额外的字节。这对答案没有影响,但就内存布局而言,这是两件完全不同的事情。向量在堆上单独的内存区域管理它们的内存,而c数组的变量实际上是在对象内存区域内分配的。缓存行为依赖于机器。如果加载一块内存,周围的内存可能也会被缓存,但缓存的内存大小与结构的外观无关,因为您的计算机不知道结构是什么,也不关心您是否认为其成员属于同一个结构。缓存线的大小是一定的,可能是128字节。如果必须访问该行中的任何字节,则会引入整行(甚至是不相关对象中的字节)。简单地说