3.4. 指令cache

并非只有处理器用到的资料有被cache;处理器执行的指令也会被cache。然而,这个cache比起资料cache,问题少了许多。有几个理由:

  • 执行的程序码的量取决于所需的程序码大小。程序码的大小一般视问题的复杂度而定。而问题的复杂度是固定的。
  • 程序的资料管理是由程序开发者所设计的,而程序的指令通常是由编译器产生的。编译器撰写者知道产生良好程序的规则。
  • 程序流程比起资料存取模式更加能够预测。现今的 CPU 非常擅于发现模式。这有助于预取。
  • 程序码总是有相当好的空间与时间局部性。

有一些程序开发者应该遵循的规则,但这些主要都是如何使用工具的规则。我们将会在第六节讨论它们。这里我们仅讨论指令cache的技术细节。

自从 CPU 核时脉急遽增加、以及cache(即使是第一层cache)与核之间的速度差距成长以来,CPU 便以管线来设计了。这表示一条指令的执行会分阶段进行。一条指令会先被解码、接著准备参数、最后再执行它。这种管线能够非常长(以 Intel 的 Netburst 架构而言,> 20 个阶段)。一条很长的管线意味著,若是管线延误了(即,通过它的指令流被中断了),它会花上一段时间才能恢复速度。管线拖延发生在 –– 举例来说 –– 下一条指令的位置无法被正确地预测、或者载入下一条指令花了太长时间(如,当它必须从memory读取的时候)的时候。

因此 CPU 设计者花费了大量的时间与晶片面积在分支预测上,以尽可能地降低管线延误发生的频率。

在 CISC 处理器上,解码阶段也会花上一些时间。x86 与 x86-64 处理器尤其受此影响。在最近几年,这些处理器因而不在 L1i 上cache指令的原始位元组序列,而是cache被解码的指令。在这种情况下的 L1i 被称作「追踪cache(trace cache)」。追踪cache令处理器能够在cache命中的情况下略过管线的前面几步,这在管线被延误时格外有效。

如同先前说过的,L2 的cache是包含程序码与资料的统一式cache。在这里,程序码显然是以位元组序列的形式被cache,而不是被解码过的。

为了达到最好的效能,只有一些与指令cache相关的规则:

  1. 产生尽可能小的程序码。有些例外,像是为了使用管线的软件管线化(software pipelining)需要建立额外的程序码的时候、以及使用小程序码的间接成本太高之处。
  2. 协助处理器做出好的预取决策。这能够通过程序布局或是显式的预取来做到。

这些规则通常由编译器的程序码产生(code generation)来强制执行。有一些程序开发者能做的事情,我们会在第六节讨论它们。

results matching ""

    No results matching ""