Intel64及IA-32架构优化指南第7章——7.4 预取

7.4 预取


这小节讨论了软件预取指令的机制。通常来说,软件预取指令应该被用于增补调整一个访问模式以适应自动硬件预取机制的实践。


7.4.1 软件数据预取


PREFETCH指令可以通过允许数据在实际使用之前来被获取,以隐藏应用程序代码中以性能为决定性因素部分的数据访问的延迟。PREFETCH指令并不改变一个程序用户可见的语义,尽管它们会影响程序性能。PREFETCH仅仅提供了对硬件的一个暗示并通常并不产生异常或错误。

PREFETCH在指定的Cache层级中要么加载非临时数据,要么加载临时数据。这种数据访问类型与Cache层级都作为一个暗示来指定。依赖于实现,该指令将32个或更多对齐的字节(包括指定的地址字节)取到该指令指定的Cache层级中。

PREFETCH是实现特定的;应用程序需要对每种实现进行调整以最大化性能。

注:PREFETCH指令只有在数据不适应于Cache中时才推荐使用。对软件预取的使用应该被限制于在应用程序的上下文内受管理的或所属的存储器地址。取没有被映射到物理页的地址会遭受不确定的性能处罚。比如,指定一个空指针(0L)作为一个预取的地址会导致很长的延迟。

PREFETCH提供了对硬件的一个暗示;它并不产生异常或错误,除了一些特殊情况(见7.4.3小节)。然而,对PREFETCH指令的过度使用可能会浪费存储器带宽,从而导致由于资源限制的性能处罚。

不过,PREFETCH可以通过防止Cache污染以及通过高效地使用Cache和存储器来减少存储器事务的负荷。这对于共享临界系统资源的应用尤为重要,诸如存储器总线。见7.7.2.1小节中的一个例子。

PREFETCH主要被设计于通过在后台隐藏存储器延迟来提升应用程序。如果一个应用程序的段以一种可预测的方式来访问数据(比如,使用已知跨度的数组),那么它们是使用PREFETCH来提升性能的良好的候选。

在以下形式中使用PREFETCH指令:

●  可预测的存储器访问模式

●  耗时的最内部的循环

●  执行流水线可能会拖延的位置,如果数据不可用的话


7.4.2 预取指令——奔腾4处理器实现


流SIMD扩展包含了四种PREFETCH指令的变种,一个非临时的和三个临时的。它们对应于两种类型的操作,临时的和非临时的。

注:在使用PREFETCH的时候,如果数据已经在一个比起由该指令所指定的Cache层更靠近处理器的Cache层,那么不会发生数据搬移。

非临时指令为:

●  PREFETCHNTA——将数据取到第二级Cache层,最小化Cache污染。

临时指令有:

●  PREFETCHNT0——将数据取道所有的Cache层;对于奔腾4处理器来说是第二层Cache。

●  PREFETCHNT1——这条指令与PREFETCHT0相同。

●  PREFETCHNT2——这条指令与PREFETCHT0相同。


7.4.3 预取及加载指令


奔腾4处理器具有一个解耦执行以及允许指令独立地与存储器访问一起执行(如果数据与资源不存在依赖)的存储器架构。程序或编译器可以使用伪加载指令来模仿PREFETCH功能;但预加载并不完全等价于使用PREFETCH指令。PREFETCH提供了比起预加载更好的性能。

当前,PREFETCH提供了比起预加载更好的性能,因为:

●  没有目的寄存器,它仅仅更新Cache行。

●  不拖延正常的指令隐退。

●  不影响程序的功能行为。

●  具有无Cache分裂访问。

●  并不引起异常,除了当使用LOCK前缀的时候。LOCK前缀并不是一个有效的与PREFETCH一起使用的前缀。

●  不会完成其自己的执行,如果那将引起一个错误。

当前,PREFETCH对预取指令的优势是处理器特定的。这在将来会有所改变。

以下是一条PREFETCH不会执行取数据的情况:

●  PREFETCH导致一次DTLB(数据翻译后备缓存)失败。这应用于相应于家族15,模型为0、1、2的奔腾4处理器上。在CPUID特征为家族15,模型3的奔腾4处理器上,PREFETCH解决了DTLB失败并取数据。

●  对引起一次错误/异常的一个指定地址的访问。

●  如果存储器子系统在第一级Cache与第二级Cache之间用完了请求缓存。

●  PREFETCH目标在一个未被Cache的存储区域(比如,USWC和UC)。

●  使用了LOCK前缀。这导致一个无效的操作码异常。

posted @ 2013-03-25 12:59  zenny_chen  Views(871)  Comments(0Edit  收藏  举报