为获得最佳性能,请尝试最小化缓存未命中。我想我们都可以同意。
我建议并想问的是以下内容。我这样说:
template <typename T>
struct {
T* a;
T* b;
T* c;
};
比以下更容易导致缓存丢失:
template <typename T>
struct {
T a;
T b;
T c;
};
我经常提出这样的说法:最小化堆分配以最小化缓存未命中。我对此有误吗?
合理性:从我的工作模拟器(我编写了包括MMU的PowerPC的模拟器):内存被拉入页面或块中。如果您在堆栈上分配所有内容,则编译器将有更好的机会将所有内容保存在连续的内存块中,这意味着提取单个页面/块将包含整个结构/类(假设您未使用巨大的结构/类),因此您的缓存未命中次数将减少。
当人们提到现代CPU时,我还不完全了解高速缓存行(我不知道它是否仅指多个高速缓存级别上的页表遍历过程)。有人告诉我,我的论点对此不正确,我不明白他们的意思。有人可以告诉我我的论证是正确的还是不正确的,以及由于x86 / x64体系结构中的特定原因而论错了?
答案 0 :(得分:2)
在堆栈或堆上,您将遇到缓存未命中的情况。所以不,这与最小化堆分配无关。
问题是处理器如何才能尽可能多地重用缓存信息并预测您要去的地方。这就是vector
比列表更好的原因,因为您正在以一种可预测的方式浏览数据(与列表或地图相比)。
所以问题是,您的struct
是一个说3 float
的结构,该结构被分配在堆上还是float
的数组?如果是第一个,然后是坏的,请使用数据本身而不是指针,如果是后者,则请使用数据,如果遍历每个数组,则具有局部性。
三个基本规则是地点,地点,地点。
然后是关于结构数组(AoS),数组结构(SoA,通常在并非所有条目都对计算有用的情况下通常更好)和数组结构数组(AoSoA,带有矢量化代码,最后一个数组)的整个讨论将被包装成浮点数/整数...)。