我希望能够手工预测确切的任意算术运算时间(例如,没有分支或内存,尽管这也很好),但考虑到指令重新排序,超标量,延迟,CPI等
要实现此目标,必须遵循哪些/描述规则?
我想我已经弄清了一些初步规则,但是我无法找到将任何示例代码分解到如此详细级别的参考,因此我不得不做出一些猜测。(例如,英特尔优化手册几乎没有提到指令重新排序。)
至少,我正在寻找(1)确认每条规则正确或对每条规则的正确陈述,以及(2)我可能忘记的任何规则的列表。
每个周期发出尽可能多的指令,从当前周期开始按顺序开始,并且可能比重新排序缓冲区的大小提前。
在以下情况下,可以在给定的周期内发出指令:
没有影响其操作数的指令仍在执行。和:
如果是浮点指令,则在发出每个浮点指令之前(浮点指令具有静态指令重排序)。和:
该指令在该周期有一个功能单元。每个(?)功能单元都是流水线式的,这意味着对于给定功能类的CPI(每个模块中的CPI不确定,例如,addps并subps使用相同的功能单位?如何确定?)。和:
4在此循环中,已经发出了少于超标量宽度(通常为)的指令。
如果没有指令可以发出,则处理器根本不会发出任何指令,这种情况称为“停顿”。
作为示例,请考虑以下示例代码(用于计算叉积):
shufps xmm3, xmm2, 210
shufps xmm0, xmm1, 201
shufps xmm2, xmm2, 201
mulps xmm0, xmm3
shufps xmm1, xmm1, 210
mulps xmm1, xmm2
subps xmm0, xmm1
我尝试预测Haswell的延迟看起来像这样:
; `mulps` Haswell latency=5, CPI=0.5
; `shufps` Haswell latency=1, CPI=1
; `subps` Haswell latency=3, CPI=1
shufps xmm3, xmm2, 210 ; cycle 1
shufps xmm0, xmm1, 201 ; cycle 2
shufps xmm2, xmm2, 201 ; cycle 3
mulps xmm0, xmm3 ; (superscalar execution)
shufps xmm1, xmm1, 210 ; cycle 4
mulps xmm1, xmm2 ; cycle 5
; cycle 6 (stall `xmm0` and `xmm1`)
; cycle 7 (stall `xmm1`)
; cycle 8 (stall `xmm1`)
subps xmm0, xmm1 ; cycle 9
; cycle 10 (stall `xmm0`)