Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 优化SSE代码_Java_C_Optimization_Sse_Intel Vtune - Fatal编程技术网

Java 优化SSE代码

Java 优化SSE代码,java,c,optimization,sse,intel-vtune,Java,C,Optimization,Sse,Intel Vtune,我目前正在为一个Java应用程序开发一个C模块,该应用程序需要一些性能改进(请参阅了解背景)。我尝试使用SSE intrinsic优化代码,它的执行速度比Java版本快一些(~20%)。然而,它仍然不够快 不幸的是,我在优化C代码方面的经验有些有限。因此,我很想就如何改进目前的实施提出一些想法 构成热点的内部循环如下所示: for (i = 0; i < numberOfGFVectorsInFragment; i++) { // Load the 4 GF-elem

我目前正在为一个Java应用程序开发一个C模块,该应用程序需要一些性能改进(请参阅了解背景)。我尝试使用SSE intrinsic优化代码,它的执行速度比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++;
    }
(i=0;i{ //从消息片段中加载4个GF元素,并将coeficent的日志添加到其中。 __m128i currentMessageFragmentVector=_mm_load_si128(currentMessageFragmentPtr); __m128i currentEncodedResult=_mm_load_si128(EncodedFragmentResult数组); __m128i logSumVector=\u mm\u add\u epi32(系数logvalueVector,currentMessageFragmentVector); __m128i updatedResultVector=\u mm\u xor\u si128(currentEncodedResult,valuesToXor); _mm_store_si128(encodedFragmentResultArray,updatedResultVector); encodedFragmentResultArray++; currentMessageFragmentPtr++; }
即使不看组件,我也可以马上看出瓶颈来自4元素聚集内存访问和
\u mm\u set\u epi32
打包操作。在您的情况下,
\u mm\u set\u epi32在内部可能会作为一系列
解包/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);
我建议将循环展开至少4次迭代,并交错所有指令,以使此代码有可能表现良好

您真正需要的是Intel的AVX2聚集/分散指令。但这需要几年的时间……

也许可以试试。
名字中带有“region”的函数应该很快。它们似乎没有使用任何特殊的指令集,但可能已经用其他方式对它们进行了优化…

您看过编译器生成的程序集了吗?可能会有一些进一步的收获。如果您无法让编译器执行这些操作,请手动执行,并使用(注释良好的).s作为源文件,而不是.cDoes,这在某种程度上扼杀了Java的“可移植性”方面。@OrangeDog我现在已将程序集添加到问题中。生成该程序集时,您是否对编译器进行过任何优化?@OrangeDog yup。我使用了以下构建标志:cl/c/Zi/nologo-/Wall/WX-/Ox/Ob2/Oi/Ot/Oy-/D WIN32/D NDEBUG/D_windell/D UNICODE/D UNICODE/Gm-/EHsc/MD/GS/arch:SSE2/fp:precision/Zc:wchar\u t/Zc:forScope/Yc“StdAfx.h”/fp”Release\NetworkCodingAccelerator.pch”/Fo“Release\\\\\\\\\\\\\\\\\\\\/Fd\Release\vc100.pdb”/Gd/TC/analyze-/errorReport:prompt Stdafx.c您认为我应该添加什么?对于MSVC的编译器设置,我是个新手。谢谢,但您的代码会产生以下错误:错误C2275:“u m128i”:非法使用此类型作为表达式。如果我删除它编译的最后三行,错误似乎与覆盖valuesToXor beceause有关(错误消息总是指向设置valuesToXor的最后一行之后的表达式)。您是否包含SSE4.1头文件
?@Mystical我甚至看到msvc实现的
\u mm\u set\u
函数作为4个副本复制到临时对齐的内存中,然后从内存加载到寄存器,看到这一点我只能摇头。@Mystical是的。例如,如果我这样写:uum128i valuesToXor=mm_cvtsi32_si128(expTable[*(logSumArray++))__m128i valuesToXor2=_mm_insert_epi32(valuesToXor,expTable[*(logSumArray++)),1);它可以编译,但如果我将其替换为:_m128i valuesToXor=_mm_cvtsi32_si128(expTable[*(logSumArray++));valuesToXor=_mm_insert_epi32(valuesToXor,expTable[*(logSumArray++]),1);编译器创建错误消息后的行。@Christian Rau:我以前也看到过。。。真是好笑。。。谢谢!它们似乎使用了许多与我类似的技巧(比如双日志表以避免额外的模)。不过,我会检查区域代码,看看他们是否还有其他优化。在阅读文档后,我实际上认为他们的代码比较慢。在对一个区域进行乘法和异或运算时,它们达到了约167MB/s。对于相同的操作,我实现了大约1GB/s(我可能有更快的CPU,但差异仍然很大)。问题是我这样做>1000/s,所以实际输出吞吐量只有~1Mb/s。