我有一个for循环,它将运行很多次,并且会耗费大量时间:
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 :(得分:3)
尝试在inArray和outArray上使用restrict
关键字。否则,编译器必须假设inArray
可以是== outArray
。在这种情况下,不可能进行并行化。
答案 1 :(得分: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
的所有操作都访问连续的内存,以便部分容易。 Psuedo-code(不展开)看起来像这样
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;
}