软件探测cpu微架构和性能

引子

几年前看到Dougall Johnson写的M1 Apple芯片微架构的材料,就一直想模仿,但是一直没有挤出时间来。

范围和背景

本文讲的芯片微架构主要是指流水线(pipeline),现在芯片pipeline一般会有几个stage,通常包括fetch, decode, execute和commit,如下图所示:

典型乱序CPU微架构

整个软件执行起来似乎如绿色箭头一样是顺序执行的,但其实decode和commit之间一般是乱序的。
decode后,会把指令顺序的放到reorder buffer中,告诉执行单元尽快干活,干完之后通知reorder buffer这个活干完了。之后由commit单元按照入对顺序把执行完的指令捞出来出队。

指令在执行过程中,会拆分成更小的单元macro-ops(mops decode单元)和micro-ops(uops dispatch单元),能拆分成多少个也叫width,或者说解码宽度(pipeline width)。
下图是ARM Neoverse V1的微架构,可以观察到每个单元的width,有多少个EU(执行单元)

ARM Neoverse V1微架构

再来一个苹果M1的对比:

Apple M1微架构

本文软件探测的范围实际上就是想覆盖上图中所有的单元,包括各个Cache,ROB大小,EUs种类个数,LSU个数。
所有代码可以参考 我的工具箱

Cache探测

Cache探测包括时延和带宽,主要通过pointer chase,这种算法已经在主流的内存测试套lmbench中实现,一般是一个数组,每个数组元素中保存一个指针,指向下一个要访问的数组元素。
通过修改步长去访问不同大小的数组,观察cache miss导致时延的变化,来判断cache大小。

更多有趣的cache影响软件行为,可以参考陈浩的这篇文章与程序员相关的CPU缓存知识

执行单元个数

主要看不同种类指令的吞吐率,可以参考uarch bench,也就是参考链接中的第一篇文章。

ROB大小

主要参考Henry Wang的测试ROB大小的文章,也放在参考链接中了。
通过填充NOP指定在两次cache miss的load中,来观察执行时间的变化,由于nop指令执行时间非常短,一旦时间变化很大,那么可以判断第二次cache miss的指令在ROB队列以外了。

参考

知道是不会有人点的,但万一有人呢:)