繁体   English   中英

我如何知道我的阵列存储在哪个缓存级别?

[英]How do I know on which cache level my array is stored?

我知道,空间和时间的局部性对性能有巨大的影响。 我不明白我的数据结构是如何存储在这些缓存中的? 为简单起见,假设 L1 缓存有 8 个字节,L2 有 16 个字节,L3 有 32 个字节。 这是否意味着如果我们有:

std::array<double, 1> x = {1.}; 
std::array<double, 2> y = {1.,2.}; 
std::array<double, 4> z = {1.,2.,3.,4.};

还有一些 function 调用这些 arrays,x 会被加载到 L1 缓存中,y 在 L2 中,z 在 L3 中吗? 或者将 y - 例如拆分为 L1 和 L2 缓存?

手动拆分这些 arrays 会在本地产生更好的缓存吗? 例如,如果我这样做:

std::array<std::array<double,2>,2> z;

当 function 调用它时,z 会在缓存级别上拆分吗?

缓存线呢? 这些通常是 64 字节长 - 将我的 arrays 拆分为 64 字节的 arrays 的 arrays 会产生更好的访问速度吗?

std::array<std::array<double,8>,2> u;

我觉得这个主题很混乱,希望能提供任何帮助

您正在以错误的方式考虑缓存。

您只能使用特殊工具(想到英特尔调试器)查看哪些缓存具有它们,并且结果将特定于您的运行和架构。 更换处理器可以很容易地破坏您的设置。

也就是说,您可以尝试使用缓存友好的解决方案。

缓存的工作方式是这样的:假设您想读取x[0] 您的程序将请求与其关联的 memory 位置。 它将被L1拦截。 如果 L1 可以给你这个值(因为它已经在一个已经存储的块中)它会。 如果不是,请求将被 L2 拦截,依此类推。 如果没有缓存级别具有该块,它将从 RAM 请求。

现在,从 RAM 中仅读取 4 个字节是低效的,因为存在开销。 所以实际上你将从 ram 中读取一个 L3 块,其中包括你想要的字节。 您可能必须读取 2 个块,因为您的数据在它们之间被拆分(编译器试图避免这种情况)。 L2 块大小的块被发送到 L2 缓存进行存储,L1 大小的块被发送到 L1,所有这些都包括您想要的字节(字节可能在中间某处)。 对于下一个请求(比如'x[1]'),同样的事情会发生。 如果下一次访问接近上一次访问,那么您可能会从 L1 获得结果。 我说可能是因为您的程序可能已在具有不同 L1 的不同内核或处理器上暂停和恢复。

尝试为特定设置进行设计通常是一个坏主意(除非您真的需要最后几%的性能并且您已经尝试过其他所有方法)。

经验法则是继续访问彼此相邻的 memory。 要避免的事情是访问相距很远的几个字节。 遍历数组非常快。 尝试在同一个排序数组上实现线性搜索和二进制搜索,看看数组需要多长时间才能从二进制搜索中获得显着更好的性能(上次我去了大约 >100 个整数)。

在您的示例中,如果您首先访问x的所有元素,然后转到y等等,则设置很好。 相反,如果您访问的是x[i], y[i], z[i]然后x[i+1], y[i+1], z[i+1]那么可能有一个结构体 {x,y ,z} 并将其放在数组中会更好(您需要进行基准测试才能确定)。

还有一些 function 调用这些 arrays,x 会被加载到 L1 缓存中,y 在 L2 中,z 在 L3 中吗? 或者将 y - 例如拆分为 L1 和 L2 缓存?

它们都将在您访问它们时加载的所有 L1、L2、L3 缓存中。 如果您经常访问,您可以从较低级别的缓存中获取它们。

手动拆分这些 arrays 会在本地产生更好的缓存吗?

不会。处理器的 memory 管理处理拆分。 缓存位置取决于您访问 memory 特定部分的频率。 最好将所有访问集中在一起,而不是随着时间的推移分散开来。

缓存线呢? 这些通常是 64 字节长 - 将我的 arrays 拆分为 64 字节的 arrays 的 arrays 会产生更好的访问速度吗?

不,您可能看不到任何区别。 arrays 由处理器中的 memory 管理内容自动拆分。 再说一次,不要为你当前的处理器架构过度优化,你明天购买的 CPU 可能有两倍长的开箱即用的缓存线。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM