优化SSE代码

Yrl*_*lec 6 c java optimization sse intel-vtune

我目前正在为Java应用程序开发一个C模块,需要一些性能改进(请参阅提高网络编码的性能 - 编码为背景).我尝试使用SSE-intrinsics优化代码,它的执行速度比Java版本快〜(约20%).但是,它仍然不够快.

不幸的是,我优化C代码的经验有限.因此,我想知道如何改进当前的实施.

构成热点的内环看起来像这样:

for (i = 0; i < numberOfGFVectorsInFragment; i++)   {

        // Load the 4 GF-elements from the message-fragment and add the log of the coefficeint to them.
        __m128i currentMessageFragmentVector = _mm_load_si128 (currentMessageFragmentPtr);
        __m128i currentEncodedResult = _mm_load_si128(encodedFragmentResultArray);

        __m128i logSumVector = _mm_add_epi32(coefficientLogValueVector, currentMessageFragmentVector);

        __m128i updatedResultVector = _mm_xor_si128(currentEncodedResult, valuesToXor);
        _mm_store_si128(encodedFragmentResultArray, updatedResultVector);

        encodedFragmentResultArray++;
        currentMessageFragmentPtr++;
    }
Run Code Online (Sandbox Code Playgroud)

Mys*_*ial 7

即使不看组件,我也可以立即告诉他们瓶颈来自4元素聚集存储器访问和_mm_set_epi32包装操作.在内部,_mm_set_epi32在您的情况下可能会实现为一系列unpacklo/hi指令.

此循环中的大多数"工作"来自打包这4个内存访问.在没有SSE4.1的情况下,我会说到循环可能更快,非矢量化,但是展开.

如果您愿意使用SSE4.1,可以试试这个.它可能更快,但可能不会:

    int* logSumArray = (int*)(&logSumVector);

    __m128i valuesToXor = _mm_cvtsi32_si128(expTable[*(logSumArray++)]);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 1);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 2);
    valuesToXor = _mm_insert_epi32(valuesToXor, expTable[*(logSumArray++)], 3);
Run Code Online (Sandbox Code Playgroud)

我建议将循环展开至少4次迭代并交错所有指令,以便为此代码提供良好的执行机会.

您真正需要的是英特尔的AVX2收集/分散指令.但那是几年后的事情......