當您寫入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;
}
你能告訴我們關於它是做什麼的嗎?什麼是A?你有沒有檢查裝配輸出? – Marco
將'z ++'改爲'++ z'通常也是個好主意 – user2485710
@ user2485710:爲什麼這裏有什麼區別? –