2013-12-13 51 views
1

我有一個循環,這將運行許多次,將花費大量的時間:任何人都可以幫助我優化這個循環使用SSE?

for (int z=0; z<temp; z++) 
{ 
    float findex= a + b * A[z]; 
    int iindex = findex ; 
    outArray[z] += inArray[iindex] + (findex - iindex) * (inArray[iindex+1] - inArray[iindex]); 
    a++; 
} 

我已經優化的代碼,但沒有性能的提高!也許我的SSE代碼很糟糕,任何人都可以幫助我嗎?

+0

你能告訴我們關於它是做什麼的嗎?什麼是A?你有沒有檢查裝配輸出? – Marco

+1

將'z ++'改爲'++ z'通常也是個好主意 – user2485710

+2

@ user2485710:爲什麼這裏有什麼區別? –

回答

3

嘗試在inArray和outArray上使用restrict關鍵字。否則,編譯器必須假定inArray可能是== outArray。在這種情況下,不可能進行並行化。

+0

嗨,謝謝你的回覆!我在for循環之外使用了多線程,所以我認爲不需要使用並行化。原來的程序有點複雜,所以我簡化了for循環。我想用simd來優化循環。可能會有與sse的表演imorove! – myej

+2

使用「restrict」關鍵字將有助於編譯器消除inArray和outArray的歧義,從而自動或半自動地向量化循環。 (我猜Kay意味着指令級並行 - 即向量化)。但是1.歧義化不足以有效地矢量化循環。正如其他人在下面提到的那樣,您還必須2.解決交叉迭代依賴性和3.考慮單位步長(連續)內存訪問。一旦你完成了它 - 編譯器應該能夠自動矢量化(對於英特爾編譯器,你也可以嘗試#pragma simd或#pragma ivdep) – zam

3

當您寫入outArray[z]時,您的循環具有循環攜帶依賴性。您的CPU可以一次執行多個浮點數,但在當前循環中,您只允許執行一次總和outArray[z]。要解決這個問題,你應該展開你的循環。

for (int z=0; z<temp; z+=2) { 
    float findex_v1 = a + b * A[z]; 
    int iindex_v1 = findex_v1; 
    outArray[z] += inArray[iindex_v1] + (findex_v1 - iindex_v1) * (inArray[iindex_v1+1] - inArray[iindex_v1]); 

    float findex_v2 = (a+1) + b * A[z+1]; 
    int iindex_v2 = findex_v2; 
    outArray[z+1] += inArray[iindex_v2] + (findex_v2 - iindex_v2) * (inArray[iindex_v2+1] - inArray[iindex_v2]); 
    a+=2; 
} 

在SIMD方面的問題是,你有當您訪問inArray[iindex_v1]收集非連續數據。 AVX2有一些收集說明,但我沒有嘗試過。否則,最好在沒有SIMD的情況下進行收集。所有訪問z的操作都可以訪問連續內存,因此部分很容易。僞代碼(沒有展開)看起來像這樣

int indexa[4]; 
float inArraya[4]; 
float dinArraya[4]; 
int4 a4 = a + float4(0,1,2,3); 
for (int z=0; z<temp; z+=4) { 
    //use SSE for contiguous memory 
    float4 findex4 = a4 + b * float4.load(&A[z]); 
    int4 iindex4 = truncate_to_int(findex4); 

    //don't use SSE for non-contiguous memory 
    iindex4.store(indexa);  
    for(int i=0; i<4; i++) { 
     inArraya[i] = inArray[indexa[i]]; 
     dinArraya[i] = inArray[indexa[i+1]] - inArray[indexa[i]]; 
    } 
    //loading from and array right after writing to it causes a CPU stall 
    float4 inArraya4 = float4.load(inArraya); 
    float4 dinArraya4 = float4.load(dinArraya); 

    //back to SSE 
    float4 outArray4 = float4.load(&outarray[z]); 
    outArray4 += inArray4 + (findex4 - iindex4)*dinArray4; 
    outArray4.store(&outArray[z]); 
    a4+=4;  
} 
相關問題