2016-11-30 97 views
2

我認爲我對延遲和吞吐量之間的差異有一個很好的理解。但是,對於Intel Intrinsics而言,延遲對指令吞吐量的影響對我來說並不明確,特別是在按順序(或幾乎按順序)使用多個內部調用時。intel intrinsics中的延遲與吞吐量有關

例如,讓我們考慮:

_mm_cmpestrc 

此爲11延遲,並且在處理器的Haswell吞吐量7。如果我在一個循環中運行這個指令,我會在11個週期後得到一個連續的每個週期輸出嗎?由於這需要一次運行11條指令,並且由於吞吐量爲7,我是否用完了「執行單元」?

我不知道如何使用延遲和吞吐量以外的時間來獲得單個指令相對於不同版本代碼所花時間的印象。

+2

吞吐量= 7表示一個可以就每7個週期。延遲= 11意味着單個結果需要11個週期。因此,平均來說,在任何給定時間約1.5,並且不超過2.(雖然這是一個多uop指令,所以調度器可能由於某種原因最終將uops從更多指令交錯)。順便說一下,Haswell上的PCMPESTRI的Agner Fog數字與英特爾的數據不匹配。) –

回答

6

有關CPU性能的更完整圖片,請參閱Agner Fog's microarchitecture guide and instruction tables。 (他的優化C++和優化彙編指南也非常出色)。請參閱標記wiki中的其他鏈接,尤其是英特爾優化手冊。

爲了分析代碼的短序列的示例,請參閱


延遲和吞吐量的單指令實際上不是足以讓爲使用的矢量指令的混合循環有用的圖片。這些數字不會告訴您哪些內在函數(asm指令)彼此競爭吞吐量資源(即它們是否需要相同的執行端口)。它們僅適用於超簡單循環,例如加載/做一件事/商店,或者例如將數組與_mm_add_ps_mm_add_epi32相加。

您可以使用多個累加器來獲得更多instruction-level parallelism,但是您仍然只使用一個內在因素,因此您確實有足夠的信息來查看例如, Skylake之前的CPU只能支持每個時鐘一個_mm_add_ps的吞吐量,而SKL可以在每個時鐘週期啓動兩個(每0.5c一個相反的吞吐量)。它可以在兩個完全流水線的FMA執行單元上運行ADDPS,而不是使用單個專用的FP-add單元,因此與Haswell(3c lat,每1c輸出一個)相比,吞吐量更好但延遲更差。

由於_mm_add_ps在Skylake上的延遲時間爲4個週期,這意味着8個矢量FP添加操作可以立即執行。所以你需要8個獨立的矢量累加器(你在最後添加到彼此)來揭示這麼多的並行性。 (例如用8個獨立的__m256 sum0, sum1, ...變量手動展開循環。編譯器驅動的展開(使用-funroll-loops -ffast-math編譯)通常使用相同的寄存器,但循環開銷不是問題)。


這些數字也離開了英特爾CPU性能的第三大尺寸:融合域UOP吞吐量。大多數指令解碼爲單個uop,但有些解碼爲多個uops。 (尤其是SSE4.2字符串指令,如您提到的_mm_cmpestrc:PCMPESTRI是Skylake上的8個uops)。即使在任何特定的執行端口上都沒有瓶頸,您仍然可以阻止前端將亂序內核控制在工作中的能力。英特爾Sandybridge系列CPU每個時鐘最多可以發佈4個融合域uops,實際上通常可以接近於其他瓶頸不會發生時的情況。 (請參閱Is performance reduced when executing loops whose uop count is not a multiple of processor width?以瞭解不同環路大小的一些有趣的最佳前端吞吐量測試。)由於加載/存儲指令使用與ALU指令不同的執行端口,因此這可能是數據在L1高速緩存中很熱時的瓶頸。

除非您查看編譯器生成的asm,否則您不會知道編譯器必須使用多少額外的MOVDQA指令才能在寄存器之間複製數據,以解決沒有AVX的情況下大多數指令會替換它們的第一條指令源寄存器與結果。 (即破壞性目的地)。您也不會從循環中的任何標量操作知道循環開銷。


我想我有潛伏期之間的差異有了深入瞭解和吞吐量

似乎你的猜測沒有什麼意義,所以你肯定失去了一些東西。

CPUs are pipelined,其中的執行單元也是如此。 A「完全流水線」執行單元可以開始一個新的操作每個週期(吞吐量=每時鐘一個)

  • (倒數)吞吐量是當沒有數據相關性迫使它等待,例如一個操作可以如何頻繁啓動該指令每7個週期一個。

  • 延遲時間是一個操作的結果準備需要多長時間,並且通常只有當它是循環運行的依賴鏈的一部分時纔有意義。

    如果循環的下一次迭代獨立於前一次操作,那麼亂序執行可能會「看到」足夠遠以在兩次迭代之間找到instruction-level parallelism並保持自己繁忙,這隻會影響吞吐量。


(未完全完成編輯工作,以後將這個整理起來。)

+0

在一個簡單的級別上,這證實了我的懷疑,即當內部函數單獨使用時,這些數字只是非常簡單。我的答案仍然不明白,哪些資源限制了多個指令(通常是相同類型)執行的順序執行。正如你所提到的那樣,執行單元的數量是一個限制。如何增加SIMD寄存器的數量? Agner的文檔,特別是微體系結構指南,對於理解各種設計方法的含義看起來特別有趣和相關。 – Jimbo

+0

是的,他們競爭的主要吞吐量資源是執行端口。例如在Haswell和後來,所有洗牌都在5號港口運行,所以它們全部相互競爭。 PADD *('_mm_add_epi8/16/32/64')可以在p1或p5上運行,所以洗牌會降低最大增加吞吐量。 (由於不按順序的亂序調度,一些PADDB指令將竊取端口5,即使混洗處於關鍵路徑但添加不是。由於uops在其操作數準備就緒後不得不等待一個執行端口,所以額外的延遲稱爲「資源衝突」。) –

+0

@Jimbo:如果編譯器用完矢量註冊表,它必須使用一些額外的加載指令。 (也許商店也是如此,如果它必須溢出臨時代碼而不是重新加載已經需要在某個時刻進入內存的內容(或者首先是隻讀)。額外的指令=額外的融合域微指令。順便說一句,謝謝你對這個答案留下的不清楚的反饋。如果/當我在匆忙發佈後重新改進它,這將有所幫助。 –