2017-07-31 89 views
0

我正在準備參加考試,並且正在做一些沒有幫助的練習。所以我一直在給這個代碼,並想知道我是否已將代碼轉換爲SIMD指令。使用SIMD指令將代碼轉換爲代碼

代碼

int A[100000]; 
int B[100000]; 
int C=0; 

for int(i=0; i < 100000; i++) 
    C += A[i] * B[i]; 

由於沒有餘,我們並不需要照顧它。我們還假定它是一個128位寄存器,因此可以計算4個單精度浮點值。

我的結果 - 使用SIMD

int A[100000]; 
int B[100000]; 
int C=0; 

for int(i=0; i < 100000/4; i += 4) 
    C += A[i] * B[i]; 
    C += A[i+1] * B[i+1]; 
    C += A[i+2] * B[i+2]; 
    C += A[i+3] * B[i+3]; 

你可以看到使用SIMD指令,而不是寫多線程程序有什麼優勢?

回答

1

假設第二個循環中省略的花括號僅僅是一個錯字,並且在for循環中有一個錯字,並且您詢問了乘法浮點數的問題,但是您的代碼顯示了整數數組,這樣甚至不會獲得很好的向量化如果編譯器看到它。雖然編譯器可能會將來自A和B的4個值加載爲單個指令,並在一條指令中執行4次乘法,但代碼會強制編譯器提取4個產品中的每一個,然後依次對它們進行求和,並逐個獲取SIMD寄存器中的值通常很慢。

如果在另一方面,你這樣做

float A[100000]; 
float B[100000]; 
float C0=0, C1=0, C2=0, C3=0; 

for (size_t i=0; i < 100000/4; i += 4) 
{ 
    C0 += A[i+0] * B[i+0]; 
    C1 += A[i+1] * B[i+1]; 
    C2 += A[i+2] * B[i+2]; 
    C3 += A[i+3] * B[i+3]; 
} 
float C = (C0 + C1) + (C2 + C3); 

然後一個很好的編譯器可以像現在vectorise這個它認爲每個循環中它加載兩個SIMD寄存器,它們相乘,則可以添加結果一個SIMD寄存器的總和,並且只提取這4個數字並且在最後總計它們。

矢量化編譯可以用SIMD來做到這一點,它不會改變個別和的評估順序(FP數學不是關聯的)。由於這個原因,編譯器通常不被允許改變FP數學的順序(不是沒有一些額外的標誌允許它在技術上違反語言標準),所以上面的代碼可以用SIMD指令精確地表示,並且運行得更快(事實上​​我會放鬆循環,因爲乘法會成爲瓶頸)。

這是SIMD的一個技巧,你必須理解,然後思考如何用矢量指令最好地實現該操作,然後編寫代碼來執行相同的操作序列,並希望編譯器能夠找到你已經完成了。

或者你也可以用intrinsics自己編寫矢量指令,或者使用OpenMP或類似的方式來更明確地告訴編譯器該做什麼。

SIMD優於線程這種操作的優勢在於,您正在單個內核中使用更多的硅片......因此您不會阻止另一個線程獲取週期。在我們的計算網格中,我們通常在任何一臺機器上運行多個單線程進程,以保持所有內核在任何時候都處於繁忙狀態......在這種情況下,使用更多內核來實現這一點是一種虛假的經濟,您只需要竊取另一個線程可能會有用地運行另一項工作。

1

是的,所提供的代碼應該編譯成帶有能力的CPU和編譯器的SIMD指令。

在支持向量的處理器上,SIMD公開了硬件特性,這些特性極大地加速了相同的並行計算。例如,由於流式RAM訪問,SIMD通常更好地利用單個內核上的緩存,假設正在處理的數據本地化在連續的內存區域中。使用多處理,緩存競爭和其他同步開銷實際上可能會降低性能,因爲各種核心試圖同時寫入數據。除了von-Neumann機器的內在增強之外,它只需要從共享系統存儲器中讀取一條而不是四條單獨的指令。

並行執行這些算術運算的邏輯總是存在,但需要使用特定的SIMD指令。因此,SIMD傾向於用於手動調節使整體優化更有意義的熱循環中。

+0

那麼,矢量化優化器可能會或者很多都不會優化任一循環,但在考試環境中,我期望看到更加明確的映射到底層架構,以闡明學生已經理解了系統的原理。特別是水平加法應該在最後進行最終摺疊時作爲矢量加法執行,特別是由於缺乏關聯性,可能會禁止等效的浮點格式。爲了避免優化器阻塞代碼複雜性,陣列的顯式對齊規範也不會受到影響。 – doynax

+0

對於考試,我希望看到這個手工編碼的目標架構的程序集,說實話。給定一箇中途體面的編譯器,儘管這個代碼應該最終被優化(在過去做了一些類似的HPC矢量,並驗證了GCC的彙編輸出)。 OP應該明確地分解二進制文件並檢查SIMD指令...... – madscientist159

+0

同意,內在函數將成爲這裏的一種方式,並且優化編譯器可以使用糾結的代碼創造奇蹟(相反,隨機分解出於難理解的原因)。在這裏最讓我困擾的是提到了「單精度浮點值」,在這種情況下,將'int'替換爲'float',剩下一個固有的串行依賴鏈,用於累積,除非使用像' - 快速數學「,並打破了過程中的大部分數字算法。老實說,除非使用並行累積緩衝區,否則我無法在考試中看到答案被接受。 – doynax