在指令開始處理后,avx 指令中用作源的暫存器何時可以重用?
例如:我想使用vgatherdps消耗兩個 ymm 暫存器的指令,其中一個是位移索引。我意識到vgatherdps收集資料需要花費大量時間,因為資料的區域性很差。
位移索引暫存器是否會在指令執行程序中被保留,或者我可以在不掛管道的情況下在后續指令中重用它?
uj5u.com熱心網友回復:
所有帶有 AVX 的 x86 CPU 都通過暫存器重命名進行亂序執行,以隱藏 Write-After-Write 和 Write-After-Read危險。看
為什么 mulss 在 Haswell 上只需要 3 個周期,與 Agner 的指令表不同?(使用多個累加器展開 FP 回圈)(關于危險和暫存器重命名的部分在我的答案頂部附近)
為英特爾 Sandybridge 系列 CPU 中的管道取消優化程式,這同樣解釋了這不是問題。
預測現代超標量處理器上的操作的延遲需要考慮哪些因素,我如何手動計算它們?
每條匯編指令需要多少個 CPU 周期?- 依賴鏈對性能很重要;暫存器重命名后,只有 RAW(寫后讀)真正的依賴關系很重要。
您永遠不必擔心由于執行讀取或寫入先前值的慢指令而導致對暫存器的只寫訪問停頓。 (亂序 exec 有其限制,物理暫存器檔案條目的數量就是其中之一,但這是與 WAR / WAW 危害不同的因素。)
暫存器重命名的全部意義在于使同一暫存器的新(獨立)使用表現得就像它們在使用不同的暫存器一樣,允許 CPU利用指令級并行性。
例如,vmovdqa ymm2, [rdi]不關心以前的指令讀取或寫入 ymm2(或其 xmm2 低半部分);vmovdqa的目的地始終是只寫的。
既然你提到了聚集,vgatherdps它本身就不是只寫它的目的地;它根據掩碼向量進行合并。因此,如果您在回圈中重復收集同一個暫存器(比如ymm0),您可能想要vpxor xmm0,xmm0,xmm0打破依賴關系。
但你可能不需要;在 Intel CPU 上,即使讀寫目標暫存器尚未“準備好”作為輸入,收集元素的實際負載也可以開始。 https://uops.info/ 在 1 個周期的延遲下測量了 Skylake 上從運算元 1 到運算元 1 的延遲。(至少當掩碼是全 1 時;對于非故障情況,這可能是特殊情況)。
因此vgatherdps ymm0, [rdi ymm5*4], ymm1可以ymm0在ymm0準備好后的周期中寫入(如果ymm5和ymm1以及指向的記憶體在 22 個周期之前準備好)。(收集吞吐量比這更糟糕;他們通過使用像 10x 這樣的指令鏈來衡量這一點vshufpd ymm0, ymm0, ymm0, 0,正如您在該鏈接的實驗 2 和 3 中看到的那樣。)
但是,例如,Zen3 上的情況就沒有那么好。Zen 3上的 vgatherdps ymm具有從運算元 1 -> 8 個周期中的 1 個的延遲。但這仍然比從索引向量就緒 -> 目標向量就緒的 28 個周期延遲短很多。(2 -> 1)
(對于掩碼向量設定為全 1 的正常聚集,您可以使用vpcmpeqd ymm1, ymm1, ymm1。它被認為獨立于先前的值,就像異或歸零習語一樣,因此即使您使用的是指令看起來像它實際上閱讀和比較。這意味著你已經打破涉及掩碼矢量的DEP鏈。有趣的是在SKYLAKE微架構,有一個從面具輸入0周期的延時輸出,如果你不刻意避免破壞依賴。查看uops.info Skylake 延遲頁面上的 3->1 部分。大概收集了諸如 vpxor-zeroing 之類的掩碼作業,只有在元素上存在頁面錯誤(或其他錯誤)時才會這樣做。)
uj5u.com熱心網友回復:
您可以在下一條指令中將該暫存器用于不同的目的。與 MIPS 等架構不同,x86 具有互鎖的流水線階段,CPU 確保后面的指令不會影響前面的指令。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/313721.html
