gpt4 book ai didi

c++ - 有多少对象(包含 std::vectors)被加载到 L1/L2/L3 缓存中?

转载 作者:太空宇宙 更新时间:2023-11-04 15:41:06 24 4
gpt4 key购买 nike

请参阅以下链接,从第 22 页开始:

http://research.scee.net/files/presentations/gcapaustralia09/Pitfalls_of_Object_Oriented_Programming_GCAP_09.pdf

上面的链接表明如果我有一个包含这样的 vector/数组的对象:

class MyClass{
public:
double a[1000];
double b[1000];
};

下面的代码遍历 MyClass 的 vector 并对 std::vector b 执行一些数学运算:

std::vector<MyClass> y;
y.populateVector();

for(auto x : y){
//Iterate though x.b and do some math;
for(int i=0; i<1000; i++){
std::cout << x.b[i] << std::endl;
}
}

当我们检索每个 MyClass 对象时,两个数组中的所有数据都将加载到缓存行中。这是真的?我没想到数据a会被加载到缓存行,因为访问b的地址会被计算和加载。

我想了解与处理所需的有用数据相比,有多少 MyClass 对象加载到缓存中?

如果第一个 b 元素与最后一个 a 元素共享相同的缓存行,我可以理解,但我不认为整个对象会加载到 L2/L3缓存只处理对象的一部分?

最佳答案

您的声明:

for(auto x : y) ...

x 声明为值而不是引用。编译器可能会优化将 y 的每个元素复制到局部变量 x 中,但我不会指望它。

如果你写:

for(auto &x : y) ...

然后循环将处理对 y 中对象的引用。我假设这就是您的意图。

具体来说,忽略struct padding:编译器会转换

double temp = y[i].b[j];

变成等同于

的东西
double temp = *(
y.data() + i * sizeof(MyClass) // start of y[i]
+ 1000 * sizeof(double) // skip over y[i].a
+ j * sizeof(double)); // get to the right place in y[i].b

它会将包含该地址的缓存行大小的 block 加载到缓存行中。

然后,当您遍历 y[i].b 的更多元素时,其中许多元素已经在缓存中。

由于每个数组包含 1000 个元素,因此它们比典型 CPU 上的缓存行大得多。 1000 个 double 占用 8000 字节,而 Sandy Bridge 架构(例如)上的缓存行是 64 字节。遍历数组将有效地使缓存饱和。您可能会在 x.a 的第一个和最后一个元素上浪费缓存行的一部分,但影响应该很小。 随着数组大小的增加,这些浪费负载的重要性接近于 0。

Playstation 文章讨论了大小与缓存行相当的对象。对于像您这样的大对象,这些优化并不重要。

关于c++ - 有多少对象(包含 std::vectors)被加载到 L1/L2/L3 缓存中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22847757/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com