Intel X86 优化指南阅读笔记--基础体系结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jqh9804/article/details/79818871

Intel Sandy Bridge Microarchitecture

流水线

  • 前端按顺序取指令和译码,将X86指令翻译成uop。通过分支预测来提前执行最可能的程序路径。
  • 带有超标量功能的执行引擎每时钟周期最多执行6条uop。带有乱序功能的执行引擎能够重排列uop执行顺序,只要源数据准备好了,即可执行uop。
  • 顺序提交功能确保最后执行结果,包括碰到的异常,跟源程序顺序一致。

这里写图片描述

前端

这里写图片描述

Legacy Decode Pipeline

  • ITLB和ICache:取指令每次16字节,利用了ITLB加速查找。
  • Instruction PreDecode:predecode unit每次接收16字节的指令流(可能含有多条X86指令)。如果指令流中含有非缺省长度的指令,则需要花费额外的3个时钟周期去解决LCP(length changing prefixe)。
  • Instruction Decode:该模块有4个解码单元。其中一个可以把x86指令最多解码成4个uop,另外三个只能解码成1个uop。这4个解码单元都支持 micro-fusion和macro-fusion技术。超过4个uop的复杂指令译码,从MSROM中获取。
  • Micro-fusion:将属于同一条指令的多个uop合并成一条复杂uop。这是因为执行单元的register renaming (RAT) 和 retirement (RRF) 阶段是瓶颈。合并成一条uop后,就只需要占用流水线一个位置。然而在执行时,依旧是像未融合前那样,发给多个port执行。它的优点:由于只产生一条uop,所以4个解码器都能对其解码。RAT和RRF由处理多条uop变成只要处理一条uop。
  • Macro-op fusion:合并多条X86指令为一条uop。该技术可以节约流水线所有阶段的带宽(从解码到结果提交)。
  • Decoded ICache:缓存了译码后的<指令地址, uop>对,这样可以省略命中指令的取指令和译码过程。cpu前端往往比后端吞吐量大,因此对后端scheduler来说,有很大的缓存uop窗口用来做优化。标准译码最多16字节指令每周期,但是使用了本cache后,可以最多32字节指令每周期。该cache学名 DSB (Decoded Stream Buffer)。
  • Branch Prediction:分支预测。
  • Micro-op Queue:uop队列作为前端和乱序引擎之间的缓冲。某些指令在uop缓冲队列中可以继续被分离为2条uop,以此获取更好的全局能耗性能。该特性被称为unlamination。
  • Loop Stream Detector (LSD):uop队列可以检测micro-op queue其中的循环指令。满足条件的循环指令可以触发LSD,从而不用再走取指令,译码之类流程,直接调用队列中的指令,直到分支预测失败。适合LSD的循环必须满足:1.最多8个chuck的指令(我理解的不准确?)。2.最多28条uop。 3.所有uop必须包含在Decoded ICache中。4.最多8条分支,并且不含有CALL和RET。5.栈操作必须匹配,比如push和pop必须数量一致。

后端

The Out-of-Order Engine

当一个执行流程再等待资源时,比如l2 cache数据,乱序引擎可以把另一个执行流程的uop发射给执行核心。

  • Renamer:每时钟周期最多发射4条uop(包括unfused, micro-fused, or macro-fused)。它的工作为:1 重命名uop里的寄存器,解决false dependencies问题。2 分配资源给给uop,例如load or store buffers。3 绑定uop到合适的dispatch port。
    某些uop可以在rename阶段完成,从而不占用之后的执行带宽。
    Micro-fused load 和store操作此时会分解为2条uop,这样就会占用2个发射槽(总共4个)。(没明白为啥之前2条uop融合为一条了现在又分解回2条)
  • Scheduler:当uop需要的资源就绪时,即可调度给下一步执行。根据执行单元可用的ports,writeback buses,就绪uop的优先级, 调度器来选择被发射的uop。
  • The Execution Core:具有6个ports,每时钟周期最多发射6条uop。指令发射给port执行完成后,需要把数据通过writeback bus写回。每个port有多个不同运算器,这意味着可以有多个不同uop在同一个port里执行,不同uop的写回延时并不相同,但是writeback bus只能独享,这就会造成uop的等待。Sandy Bridge架构尽可能消除改延时,通过把不同类型数据写回到不同的execution stack中来避免。

Cache Hierarchy

这里写图片描述

Load and Store Operation

Load

这里写图片描述
LLC包含了L1和L2的内容,并且对每个cache line,含有一个指示数据,标记了含有该cache line内容的所有核心。当一个对L1和L2的数据查询不需要从其它核心的cache读取,称作"clean"。如果需要从其它核心的cache读取被修改了的数据,则称作"dirty"。

当被修改了的cache line被替换出去时,它需要写回内存,这将占用cache和内存带宽。如果短时间内,由于大量cache miss导致修改了的cache line被写回内存,这将降低cache的全局响应时间。

Stores

对于写回类型的内存,在写入数据前需要把内存里的数据读取到L1 cache中,并且是Exclusive或者Modified状态(MESI协议)。否则,处理器需要使用
Read for Ownership request来获取最新的数据,其顺序为:

  1. L1 Dcache
  2. L2
  3. LLC
  4. 其它核心的L1 和 L2
  5. 内存
    一旦cache line读取到了L1中,新数据即可写入,并标记为Modified(MESI协议)

Reading for ownership和storing the data发生在指令retirement后,所以store延时通常不会影响store指令。然而,太多的连续store导致L1 miss可能会累加这种延时,从而影响性能。只要store没有真正完成,它将一直占用store buffer,如果这个buffer满了。新的uop将无法执行。

L1 DCache

L1 Dcache也可以投机和乱序执行load,store操作。它的组件包含:
这里写图片描述

  • DUC大小32KB,8路组相连,每个cache line有8个bank.
  • Cache内部每次最多访问16字节。每个时钟周期可以执行2条load指令和1条store指令。
  • L1 能够同时维护最多64条load指令(从分配到最后发射过程中),最多32条store指令(从分配到最后发射过程,或者从分配到写入LFB)
  • L1 能在没处理完多个cache缺失的同时继续服务后续store和load指令(利用LFB可以同时处理最多10个未解决的cache缺失)。
  • store执行时,如果数据在L1中,那么直接修改不会传递到L2,LLC,如果不在L1中,则需要分配一个新的cache line。

Load

L1每个时钟周期能够为2条load指令服务,每条指令最多读取16字节。整个cache能缓存32条load指令。整个生命周期从乱序引擎分配load指令到最后读取成功返回给执行核心。
Load能做到:

  • 如果store地址跟load地址范围没有冲突,load可以提前执行。
  • 在分支跳转没有确定前,投机执行。
  • cache缺失时能够乱序执行。

Load不能做到:

扫描二维码关注公众号,回复: 3526547 查看本文章
  • 投机执行任何fault或trap。
  • 投机访问不能cache的内存。

Store

store操作分为两步:

  • 执行阶段,把地址和数据填充到store buffer中,一旦地址和数据已知即可直接传递给需要的load操作作为源。
  • 完成阶段,store指令发射后,L1把数据从store buffer移动到DCU,最多16字节。

Store Forwarding
如果store后面紧跟着load指令,在满足条件的情况下,可以直接把store的输出传递给load指令,这样就避免了对L1 cache的访问。

Memory Disambiguation
load指令可能依赖于之前的store指令。这里可以投机执行,在不知道store数据地址的情况先load数据,最后再做验证。

Bank Conflict
load指令最多16字节,最多跨越3个bank(不对齐情况下可能跨越3个bank)。每周期2条load指令最多跨越6个bank。如果这两个load指令访问的bank有重叠并且在不同cache组中,那就发生了冲突,其中一条load只能之后重新执行。如果是同一个组中的bank则可以并发执行。

Ring Interconnect and Last Level Cache

LLC通过一个ring总线把cpu核心与图形单元,LLC,system agent连接在一起。
LLC被所有cpu核心共享,分成多个slices,数量跟核心数量相同。每个slice每时钟周期可以访问32字节。每个slice分为逻辑部分和数组部分,前者用来处理同步问题,后者用来保存数据。
数据通过对其物理地址进行hash计算后保存到对应slice。
从cpu核心的角度看,LLC是一个多端口组件,带宽随着cpu核心数目增加而增加。LCC的命中延时在36-31个时钟周期之间,具体数值依赖于cpu核心与数据所在的LLC slice距离有关。

Data Prefetching

数据能够被投机加载到L1中,手段有软件预取和硬件预取。
软件预取有四种,可以指定数据加载到不同层级的cache中。
硬件预取:

  • 如果数据被安排成顺序访问,那么硬件预取会提高性能。
  • 如果数据被安排成稀疏分布,那么可能由于带宽限制造成轻微性能下降。
  • 如果cahce已被占用大多数,而且这些数据都是热数据不需要要被替换,预取会导致性能严重下降。

System Agent

包含如下组件:

  • 仲裁器用于路由ring domain和IO(pcie,dmi)到正确的位置。
  • PCIe控制器。
  • DMI控制器,用于连接南桥和北桥总线。
  • 图形引擎。
  • 内存控制器。

所有cpu访问内存的流量都要通过仲裁器路由到内存控制器。内存控制器支持双通道ddr。内存访问对地址进行哈希,均衡分不到不同通道中,最大化带宽利用。
内存控制器的两个通道有独立的资源,可以独立处理内存访问。内存控制器有一个乱序调度器,可以尝试最大化内存带宽,最小化延时。每个内存通道含有write-date-buffer,包含了32个cache line。内存写入操作,当写入这个buffer时操作就会返回,随后会刷新进入内存。
内存控制器对不够一条cache line的数据写入处理不够高效。软件应该尽可能的凑齐一个cache line在写入。

超线程

Intel® Hyper-Threading Technology (HT Technology)技术在一个物理核心上模拟多个逻辑处理器。绝大多数intel cpu可以模拟2个逻辑处理器(超线程),以下只考虑该情况。
物理核心上的两个逻辑处理器既有自己独占的资源,也有共享的资源。
在这里插入图片描述
超线程下的性能取决于:

  • 需要有多个线程跑满逻辑处理,并同时执行。
  • 超线程共享物理核心的执行引擎。因此,执行引擎利用率越高,系统吞吐量越大。(我认为只要监控执行引擎吞吐量,就可以衡量超线程的性能提升效果)。

Processor Resources and HT Technology

Replicated Resources

每个逻辑处理独自拥有的资源:
有关保存微架构状态的寄存器:eight general-purpose registers, the control registers, machine state registers, debug registers等等。
指令寄存器,寄存器重命名表,return stack predictor。

Partitioned Resources

部分资源被逻辑处理均分独立使用,这是为了:

  • 操作的公平性
  • 如果一个逻辑处理被阻塞了,另外一个逻辑处理还能不受影响继续执行。
    a cache miss, a branch misprediction, or instruction dependencies经常会导致逻辑处理器流水线停滞。
    会被均分使用的资源有:前端处理完后的uop queue,寄存器重命名后的queue,执行引擎完后顺序提交前的reorder buffer,load和store buffer。

Shared Resources

绝大多数资源会被逻辑处理器共享,包括各级cache和执行单元。

Microarchitecture Pipeline and HT Technology

执行单元被逻辑处理器共享,因此执行单元的前端和后端有多个选择点需要从多个逻辑处理器中选择指令来执行。所有选择点会轮替从逻辑处理器中选择指令,如果逻辑处理器指令流水线停滞了,那就选择另外一个逻辑处理器的指令。
造成流水线停滞的原因通常包括:cache misses, branch mispredic- tions, and instruction dependencies。

Front End Pipeline

execution trace cache被逻辑处理器共享,逻辑处理器交替使用它,除非逻辑处理停滞了。
前端译码后的uop会放到一个queue中,这个queue被逻辑处理器均分,互不影响。

Execution Core

执行单元每时钟周期可以发射6条uop。一旦uop被放入待发射队列,执行单元不区分该uop属于哪个逻辑处理器。
uop执行完成后,会被放入re-order buffer,这个buffer被逻辑处理器均分,互不影响。

Retirement

顺序提交被逻辑处理器交替使用,同样的,如果一个逻辑处理器停滞了,那就继续执行另外一个逻辑处理器。

猜你喜欢

转载自blog.csdn.net/jqh9804/article/details/79818871
今日推荐