商湯科技高性能計算組總監高洋:浮點峰值那些事兒

CPU X86 齊文宣帝 英特爾 AI科技大本營 AI科技大本營 2017-08-27

商湯科技高性能計算組總監高洋:浮點峰值那些事兒

本文作者高洋,目前在商湯科技高性能計算組擔任總監,對於並行計算頗有心得。本篇為高洋寫給高性能並行計算的初學者,核心內容是教初學者用科學手段測量硬件的理論指標。有了這個指標,就能對硬件的能力上限有更深入瞭解,知道優化工作做到了什麼程度,是否還有上升的空間。

此篇乾貨滿滿,如果你對高性能計算感興趣,本篇絕對不可錯過。

作者 | 高洋

整理 | AI科技大本營(rgznai100)

這個系列的第一篇文章,先談點輕鬆的,常用CPU架構浮點峰值的理論計算和實測。做性能優化,先要知己知彼,瞭解自己優化的CPU的能力上限。這樣優化做到什麼程度,心裡會有數。

本文只介紹Intel x86-6486-6486-6486-6486-64架構,並且只針對單精度float類型。浮點峰值的計算,一般是計算單位時間內,乘法和加法的最大總吞吐量,單位是GFLOPS或者TFLOPS,表示每秒鐘計算乘法和加法的總次數。

乘法和加法可能涉及到的指令包括:單獨的乘法指令,如vmulps;單獨的加法指令,如vaddps;融合乘加指令,如vfmadd231ps等。後者將乘法和加法融合為一條指令,在多數處理器中,三種指令都可以在一個發射端口每週期發射一條,所以乘加指令往往比單獨使用乘法或者加法帶來翻倍的吞吐量。

先來看x86-64,Intel在2010年推出Sandy Bridge架構(下面簡稱SNB),首次引入了256位寬的向量指令集AVX,即一條指令可以同時操作8組32位寬的數據類型。SNB架構示意圖如下:

商湯科技高性能計算組總監高洋:浮點峰值那些事兒

六個dispatch ports,其中port0和port1各有一條向量乘法(256-FP MUL)和向量加法(256-FP Add),即一個週期內,SNB架構可以吞吐一條浮點向量乘法和浮點向量加法。由於AVX指令集還不支持融合乘加FMA,浮點峰值計算只能使用這兩條指令的總和吞吐量。

綜上所述,SNB架構的理論浮點峰值就等於(8Mul + 8Add) * 核心頻率 * 核心數。例如SNB桌面高端的i7 2600k,有四個核心,關閉睿頻後每核心頻率3.4GHz,所以這款CPU的理論浮點峰值(關閉睿頻)就是(8+8)*3.4*4=217.6GFLOPS。

如果想寫一個小程序實測的話,可以這樣設計:設置一個簡單的循環,次數足夠多,保證每次循環執行一個時鐘週期,發射兩條無依賴的vmulps和vaddps指令:

.loop:

.loop是循環體;前兩條vmulps和vaddps指令,輸入和結果使用不同的寄存器,這樣前後兩個相鄰循環的同一條指令產生WAW型寄存器依賴,通過寄存器renamer部件可以解決;然後用sub指令每次給rax寄存器裡的循環計數減一,如果減到0,會修改狀態寄存器的值,jne指令不會跳轉,循環結束。sub指令和jne指令在SNB架構下和可以做到宏融合,形成單一的微指令,不會產生延遲,在port5和前面的乘法加法同週期分派。

由於本人手頭沒有SNB架構的處理器,暫時不能測試。SNB下一代微架構Ivy Bridge只是工藝升級版的SNB,各種特性幾乎和SNB一樣。我們再看下一代,即2013年推出的Haswell架構:

商湯科技高性能計算組總監高洋:浮點峰值那些事兒

Haswell架構增加了AVX2和FMA指令集,其中FMA指令集就是256位的融合乘加指令,根據架構圖中所示,port0和port1端口各有一個FMA單元,所以Haswell架構的理論峰值就等於2port * 8 * 2(mul+add) * 頻率 * 核心數。例如i7系列的最高版本i7 4790k,四核心,關閉睿頻固定4GHz頻率,那麼浮點峰值就是2 * 8 * 2 * 4 * 4 = 512 GFLOPS,每個核心的峰值就是128 GFLOPS。

如果要實測Haswell的理論峰值,與SNB大部分思路是相同的。除了用到不同的指令以外,與SNB還有如下一些區別:fma指令的某個參數寄存器,既做輸入也做輸出,這樣前後兩個相鄰循環間的同一條fma,就形成了RAW型寄存器依賴。所以如果每個循環還要求一個週期執行,併發射兩條fma指令,相鄰循環間肯定就會有數據依賴發生,要等待前一個循環的兩條fma執行完畢才能進行第二次循環的兩條fma,這就會導致流水線停頓,浪費時鐘週期。假設fma指令的執行週期是k,那麼解決辦法就是一次循環內安排2k個數據無依賴的fma指令。經過試驗,我們發現放10條fma指令到一個週期,浮點吞吐剛好達到最大值:

.loop:

所以haswell架構下fma指令的執行延遲就是5個週期。感興趣的同學可以試試改變循環內fma指令數量,看看測出來的GFLOPS有何變化。

我在自己的i7 4790k上測試了這個例子,結果如下:

商湯科技高性能計算組總監高洋:浮點峰值那些事兒

測試同時包含了單精度和雙精度兩種,分如下四種情況:單線程,雙線程,四線程和八線程。i7 4790k是四核八線程的處理器,所以根據前三組測試可以發現,實測峰值和理論峰值極為接近,與使用核心數量嚴格成比例。最後一組八線程使用了i7處理器的八個超線程,發現測出來的值和四線程幾乎一樣。這是由於超線程只是為每個核心提供兩組線程上下文單元,兩個線程其實是共享各種核內運算部件的。超線程的好處是線程之間往往沒有各種數據依賴關係,兩個線程的指令流可以儘量填充流水線並充分利用亂序多發射能力。互相掩蓋對方的各種延遲,提高每個核心的利用效率。我們這個測試程序已經完整地利用了浮點乘加的吞吐能力,所以超線程並不帶來好處。

同樣的方法也可以測試ARM架構的CPU浮點峰值,但是需要注意ARM NEON指令包含兩種乘加方式:向量乘向量,以及向量乘標量。注意這兩種方式的指令延遲可能是不一樣的,差距甚至會比較大,需要分別測出兩者的延遲。Intel也已經推出了基於Skylake-X架構的AVX512指令集的Xeon服務器CPU,在FMA指令的基礎上又提升了一倍的浮點峰值性能。新的架構很有意思,高端版本支持一個週期發射兩條AVX512版本的乘加指令,其中一條來自port0和port1的256位FMA的端口融合,另外一條來自port5。中低端版本的Skylake-X就去掉了port5的乘加單元,只與Haswell的浮點能力相當。大家在選購服務器的時候一定要考察清楚。

有了峰值性能的數據,我們在寫矩陣乘法和卷積運算這些計算密集型算法的時候,就有了一個理論上限。通過測試結果與理論上限的差距,評估算法的可能優化空間。除了浮點峰值性能,還有很多處理器的指標對我們優化和評估程序性能都有重要意義,例如內存帶寬和延遲,各級cache的帶寬和延遲,分支預測失敗的懲罰週期...... 本文就不一一展開詳述了。

上面測試彙編代碼的完整版本我放在了github上:pigirons/cpufp

https://github.com/pigirons/cpufp

參考資料:

[1] Intel® 64 and IA-32 Architectures Software Developer’s Manual

[2] Intel® 64 and IA-32 Architectures Optimization Reference Manual

[3] 《探求計算性能的極限》,王琤

[4] Intrinsics Guide

https://software.intel.com/sites/landingpage/IntrinsicsGuide/

原文地址

https://zhuanlan.zhihu.com/p/28226956

相關推薦

推薦中...