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)
即使不看组件,我也可以立即告诉他们瓶颈来自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收集/分散指令.但那是几年后的事情......