任何人都可以帮我优化这个循环使用SSE吗?

时间:2013-12-13 01:56:44

标签: c performance optimization sse

我有一个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代码很糟糕,任何人都可以帮助我吗?

2 个答案:

答案 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;      
}