【问题标题】:which is optimal a bigger block cache size or a smaller one?更大的块缓存大小或更小的块缓存哪个是最佳的?
【发布时间】:2018-03-14 18:15:23
【问题描述】:

给定具有恒定容量和关联性的缓存大小,对于确定数组元素平均值的给定代码,是否会首选具有更大块大小的缓存?

[来自 cmets]

检查下面给出的代码来计算数组的平均值:

total = 0; 
for(j=0; j < k; j++) { 
  sub_total = 0; /* Nested loops to avoid overflow */ 
  for(i=0; i < N; i++) { 
    sub_total += A[jN + i]; 
  } 
  total += sub_total/N; 
} 
average = total/k;

【问题讨论】:

  • 完全不清楚你在问什么。你能给我们举个例子吗?通常,对“什么大小的缓存更好”问题的回答是,“这取决于您的数据和访问模式。”
  • 检查下面给出的代码以计算数组的平均值:total = 0; for(j=0; j / for(i=0; i N + i]; } 总计 += sub_total/N; } 平均 = 总数/k;
  • 编辑您的问题并将代码放在那里,最好格式化以提高可读性。无法理解 cmets 中的代码。

标签: algorithm caching optimization cpu-architecture


【解决方案1】:

从您的示例代码中,我们不能说任何一种方式,只要硬件预取器能够以最大内存吞吐量保持内存流。

在随机访问场景中,较短的缓存行可能更可取,因为您不需要填充所有行。但是缓存内存的总量会下降,因为您需要更多的标签电路和可能更多的比较时间。

因此必须做出妥协,英特尔选择了每行 64 字节(并获取 2 行),其他人选择了每行 32 字节。

【讨论】:

    【解决方案2】:

    相关:在具有一些但有限的空间局部性的典型访问模式的更一般情况下,较大的线在一定程度上有所帮助。这些 "Memory Hierarchy: Set-Associative Cache" (powerpoint) 幻灯片由 Hong Jiang 和/或 Yifeng Zhu(美国缅因州)提供了 AMAT(平均内存访问时间)与块大小的曲线图,同时也打破了它归结为未命中惩罚与未命中率(我认为对于一个简单的模型,对于一个简单的有序 CPU,它在隐藏内存延迟方面很糟糕。例如,甚至可能没有流水线处理多个独立的未命中。(未命中下的未命中))

    在这些幻灯片中很多好东西,包括提到循环交换的编译器优化部分(以修复列优先与行优先顺序的嵌套循环),甚至缓存阻塞以实现更多重用。互联网上的很多东西都是废话,但我浏览了这些幻灯片,它们提供了一些关于如何设计缓存以及权衡取舍的可靠信息。性能分析的东西只对简单的 CPU 真正准确,不像现代的乱序 CPU,它可以与缓存未命中延迟重叠一些计算,因此较短的未命中与较少的较长未命中是不同的。


    这个问题的具体答案

    所以您唯一关心的工作负载是元素的线性遍历?假设良好的硬件预取,这使得高速缓存行大小与性能几乎无关。 (因此,更大的线路意味着相同性能的硬件复杂性和功耗更低。)

    使用软件预取,更大的行意味着更少的预取开销(尽管取决于 CPU 设计,如果您仍然最大限度地利用内存带宽,这可能不会影响性能。)

    在没有任何预取的情况下,更大的行/块大小将意味着在每次需求未命中后会有更多的命中。数组的单次遍历具有完美的空间局部性,没有时间局部性。 (实际上,如果数组未与缓存行的开头对齐,和/或在行的中间结束,则在开始/结束处的空间局部性实际上并不完美。)

    如果未命中必须等到整个行都存在于缓存中才能满足导致未命中的负载,这会略微降低较大块的优势。 (但缓存未命中的大部分延迟在于信令和请求开销,而不是等待突发传输已经开始后完成。)

    更大的块大小意味着在相同带宽和延迟的情况下运行中的请求更少,而有限的并发性是实际 CPU 中内存带宽的真正限制因素。 (有关 x86 内存带宽,请参阅此答案的latency-bound platforms 部分:对 L3 缓存具有较高延迟的多核 Xeon 的单线程带宽低于相同时钟速度的双核或四核。每个内核只有 10 行-填充缓冲区以跟踪未完成的 L1 未命中和bandwidth = concurrency / latency。)

    如果您的缓存未命中处理具有提前重启设计,那么即使是那一点额外的延迟也可以避免。 (这很常见,但保罗说theoretically possible to not have it in a CPU design)。导致丢失的负载一到达就得到它的数据。缓存行的其余部分填充“在后台”发生,希望以后的加载也可以从部分接收的缓存行中得到满足。

    Critical word first 是一个相关功能,首先发送所需的字(用于提前重启),然后突发传输回绕以传输块的较早字。在这种情况下,关键字始终是第一个词,因此除了提前重启之外不需要特殊的硬件支持。 (我在上面链接的 U. Maine 幻灯片首先提到了提前重启/关键词,并指出它减少了大型缓存行的未命中惩罚。)


    无序执行 CPU(或按顺序 CPU 上的软件流水线)可以通过同时处理多个未完成的需求未命中来为您提供相当于硬件预取的功能。如果 CPU“看到”另一个缓存行的负载,而当前缓存行的未命中仍然未完成,则可以对需求未命中进行流水线化,再次隐藏较大或较小行之间的一些差异。

    如果行太小,L1D 可以跟踪的不同行的未完成未命中数会受到限制。对于较大的行或较小的无序窗口,当没有对下一个缓存行的未完成请求时,您可能会有一些“松弛”,因此您不会最大化带宽。当你到达缓存行的末尾并且下一行的开始还没有到达时,你会用管道中的气泡来支付它,因为它开始得太晚了(而 ALU 执行单元使用的数据距离太近当前缓存行的结尾。)


    相关:these slides 不用多说大线与小线的权衡,但看起来还不错。

    【讨论】:

      【解决方案3】:

      简单的答案是更大的缓存块将是首选,因为工作负载没有(数据)时间局部性(没有数据重用),完美的空间局部性(不包括第一个块的阵列可能不充分的对齐以及最后一个块的数组,每个数据块的每个部分都将被使用)和单个访问流(没有潜在的冲突丢失)。

      更细致入微的答案是考虑数组的大小和对齐方式(第一个和最后一个缓存块中未使用的部分以及所代表的内存传输时间的部分;对于 1 GiB 数组,甚至 4 KiB块将浪费不到 0.0008% 的内存带宽),系统首先使用关键字的能力(如果数组大小适中,并且不支持在数据可用时提前使用数据,而不是等待整个块被填充,那么启动开销将消除较大缓存块的大部分预取优势),使用预取(软件或硬件预取降低了大缓存块的好处,这种工作负载对预取非常友好) ,内存系统的配置(例如,使用带有立即页面关闭控制器策略的 DRAM 将增加更大缓存块的好处,因为每次访问都会涉及行激活和行关闭,通常是相同的DRAM bank 防止延迟重叠),指令和页表访问是否使用相同的块大小以及这些访问是否共享缓存(指令访问提供了第二个“流”,它可能会引入冲突未命中;使用两级分层页表的共享缓存,TLB 未命中将访问两个缓存块),是否使用简单方式预测(更大的块将提高预测精度,减少误预测开销),以及可能的其他因素。

      【讨论】:

      • 在您的统一 L1 示例中,指令获取不会将指令保留在 MRU 位置吗?不过,有趣的想法。在我的回答中,我不确定简单的设计是否必须等待整个缓存行到达才能满足第一个单词的负载。 (即,当关键字是第一个时,甚至不会表现得像关键字在前。)这会降低大行的优势,但只是轻微地因为很多延迟是设置请求(和 DRAM 信号),而不是等待实际的突发传输。
      • @PeterCordes 是的(尽管循环缓冲区可能会使向量指令和深度流水线变得复杂)。系统理论上可能不支持提前重启; 可能等待甚至会带来很小的能源效率优势。 (我也没有考虑扇区缓存块,它可以减少重新填充延迟或对 DRAM 突发长度的影响。)这种类似家庭作业的练习更有趣的是掌握他们假设的内容(例如,没有预取)以提供一个简单的模型对于初学者来说比提供预期的答案。
      • 是的,有趣的是,现代现实世界的桌面 CPU 是多么的不简单。这让我想起了臭名昭著的"deoptimizing a C++ program (for Haswell)" 问题,它询问“利用您对 Intel i7 管道如何运行的知识。想象一下重新排序指令路径以引入 WAR、RAW 和其他危险的方法。”但是,正如我的回答所解释的那样,寄存器重命名当然意味着没有 WAR 或 WAW 危害:P 有趣的是,分配它的教授实际上发布了它:meta.stackoverflow.com/a/323690/224132
      • 让我想知道他们实际教的是什么,以及它是否更像是经典的 RISC 流水线而不是实际的英特尔 i7 流水线!写出来的答案仍然很有趣,但可能不像教授认为的正确答案那样。
      猜你喜欢
      • 2022-11-10
      • 1970-01-01
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      • 2012-01-28
      • 1970-01-01
      • 2013-07-05
      • 2011-02-25
      相关资源
      最近更新 更多