缓存控制指令
在计算中,缓存控制指令是嵌入处理器指令流中的提示,旨在利用程序员或编译器提供的关于内存访问模式的信息来提高硬件缓存的性能。 [1]它们可以通过更好地控制工作集来减少快取污染、减少带宽需求、绕过延迟。大多数缓存控制指令不会影响程序的语义,尽管有些可以。
例子
此类指令受多个处理器指令集架构的支持,例如ARM、MIPS、PowerPC和x86。
预取
也称为数据缓存块触摸,其效果是请求加载与给定地址关联的缓存行。这是由x86指令集中的PREFETCH
指令执行的。一些变体绕过更高级别的缓存层次结构,这在“流式”上下文中对于遍历一次而不是保存在工作集中的数据很有用。预取应该发生得足够早,以减轻内存访问的延迟,例如在使用循环来线性遍历内存时。 GCC内置函数__builtin_prefetch
可用于在编程语言C或C++中调用。
指令预取
预取的一种变体,适用于指令缓存。
数据缓存块无效化
此提示用于丢弃缓存行,而不将其内容提交到主内存。该指令可能会带来不正确的运行结果,因此需要谨慎使用。与其他缓存提示不同,这条缓存提示会极大地改变程序语义。这与allocate zero
一起用于管理临时数据。这节省了不需要的主内存带宽,避免缓存污染。
数据缓存块刷新
此提示请求立即牺牲一个缓存行,为即将发生的分配让路。当已知数据不再是工作集的一部分时使用它。
替代方案
自动预取
最近,英特尔和ARM开发的越发先进的应用处理器将更多的晶体管用于加速用传统语言编写的代码,例如执行自动预取、使用硬件来动态检测线性访问模式。因而缓存控制指令变得不那么流行了。然而,这些技术可能对面向吞吐量的处理器仍然有效,它们具有不同的吞吐量-延迟的侧重性,并且可能更倾向将更多区域用于执行单元。
暂存器内存
一些处理器支持将临时文件放入暂存器,并使用直接記憶體存取(DMA)在需要时将数据传入传出主内存。 Cell 处理器和一些嵌入式系统使用这种方法。这些允许更好地控制内存流量和位置(因为工作集由显式传输管理),并消除了对多核机器中昂贵的快取一致性的需求。
缺点是它需要使用截然不同的编程技术。很难改写用传统语言(如 C 和 C++)编写的程序,这些语言向程序员提供了一个大地址空间的统一视角(这是通过缓存模拟出来的错觉)。传统的微处理器可以更轻松地运行遗留代码,然后可以通过缓存控制指令对其进行加速,而基于暂存器的机器则需要从头开始进行专门编写,直至能实现相同功能。缓存控制指令特定于某个缓存行大小,在实践中,同一体系结构系列中的处理器各代之间可能不同。缓存还可以帮助从不可预测的访问模式(例如,在材质贴图的过程)中合并读取和写入,而暂存器 DMA 需要重新设计算法以实现更可预测的“线性”遍历。
此类暂存器通常更难与传统编程模型一起使用,不过对于資料流模型(例如TensorFlow)而言可能更合适。
参考资料
- (PDF). [2022-12-19]. (原始内容 (PDF)存档于2016-10-13).