前向兼容手札 头像

消息来源频道

前向兼容手札

@zyf_at_rochester

频道122 位成员公开可见0 人在线

后向兼容什么的,才没人在意呢!

成员规模122 位成员
在线情况0 人在线
消息总数888 条消息
浏览量总数15,140 次浏览

在这个频道里搜索消息……

t.me/zyf_at_rochester

因为现代 CPU 都是超标量的,有多个功能单元(比如两个算术逻辑单元 + 一个浮点运算单元 + 别的),可以一次性发射多条指令到不同的功能单元一起计算,因此一个 cycle 内实际上可以执行多条指令,称之为 instruction-level parallelism(ILP)。当然高并行的前提是有足够的功能单元以及指令之间没有依赖。有关内容可以阅读一下《现代处理器结构》。
我还在用 zen2 没有 TMA 可用。但对于这个场景有非常适合的工具:uiCA 和 llvm-mca。
举个例子,这里的无脑算法我们在 godbolt.org 用 gcc15.2 + O3 编译得到循环体部分的汇编如下:
.L3:
movsd xmm2, QWORD PTR [rax]
add rax, 8
mulsd xmm2, xmm0
mulsd xmm0, xmm3
addsd xmm1, xmm2
cmp rdx, rax
jne .L3
把这串代码丢到 uiCA 模拟,可以得到结果是 4 cycles per iteration。而霍纳算法是 8 cycles per iteration。但是为什么呢?
在 HTML output 里面打开 Trace Table,里面有流水线的可视化模拟,包括指令使用了哪个端口、在第几个周期发射(I)、调度(D)、执行(E)、退役(R)等等。如果调度等了很久,那可能是端口不太够;如果退役等了很久,那可能是指令之间有依赖。在霍纳算法的图里,我们可以看到超长的 E->R 距离,所以降低 IPC 的主因就是指令间依赖了。更多有关 Trace Table 的信息,可以看《Visualizing Performance-Critical Dependency Chains》。