将浮点数相乘和相加
我有一项任务是将一些C++代码转换为ASM,我想知道我的想法是否有意义。首先,我会将整数转换为浮点数。我想得到数组数据到SSE寄存器,但这里有问题,因为我只想要3而不是4个整数,有什么方法可以克服这个问题吗?然后,我将使用CVTDQ2PS将这些整数转换为浮点数,并将这些数字保存在内存中。对于像0.393这样的常量数字,我会做3个浮点数的矢量,然后我会做同样的操作三次,所以我只考虑sepiaRed。为此,我会将转换后的整数放入SSE寄存器,然后将这些数字相乘,这将得到xmm0寄存器中的结果。现在如何将它们相加?
我想我的两个问题是:如何将3个项从数组获取到SSE寄存器,这样我就可以避免任何问题。然后如何将xmm0寄存器中的三个数字相加在一起。
tmpGreen = (float)pixels[i + 1];
tmpRed = (float)pixels[i + 2];
tmpBlue = (float)pixels[i];
sepiaRed = (int)(0.393 * tmpRed + 0.769 * tmpGreen + 0.189 * tmpBlue); //red
sepiaGreen = (int)(0.349 * tmpRed + 0.686 * tmpGreen + 0.168 * tmpBlue); //green
sepiaBlue = (int)(0.272 * tmpRed + 0.534 * tmpGreen + 0.131 * tmpBlue); //blue
解决方案
您不能轻松地将3个数字水平相加;Fastest way to do horizontal SSE vector sum (or other reduction)
您可以高效地并行映射4个像素,并带有4个红色、4个绿色和4个蓝色的矢量。(您可能希望从平面的、而不是交错的像素数据中加载。数组的结构,而不是结构的数组。)如果您只使用movdqu
加载4个int,并对cvtdq2ps
之后的高元素使用乘数0.0
,则一次处理单个像素可能会获得一些好处。然后你可以做一个正常的4个元素的水平和,而不是必须调整它。(嗯,尽管做3会让你在第一次加的同时进行第二次洗牌,而不是在之后。)
低效使用SIMD会失去一些好处;请参阅https://stackoverflow.com/tags/sse/info特别是https://deplinenoise.wordpress.com/2015/03/06/slides-simd-at-insomniac-games-gdc-2015/Re中的指南:人们如何经常尝试使用一个SIMD矢量来容纳一个x,y,z几何矢量,然后发现SIMD没有太大帮助。
相关文章