问题:
我将MMX转换为代码到相应的SSE2代码。而且我预计加速几乎是1.5倍-2倍。但两者完全相同。为什么?
情境:
我正在学习SIMD指令集及其性能比较。我进行了一个数组操作, Z = X^2 + Y^2
,其中X和Y是“char”类型的大型一维数组。 X和Y的值被限制为小于10 ,因此Z总是 <255(1字节)。 (不要担心任何溢出)。
我先写了它的C ++代码,检查了它的时间。然后编写相应的ASSEMBLY代码(~3x加速)。然后我写了它的MMX代码(~12x v / s C ++)。然后我将MMX转换为SSE2代码,它的速度与MMX代码完全相同。从理论上讲,在SSE2中,我预计与MMX相比,加速比为2倍。
为了从MMX转换到SSE2,我将所有mmx reg转换为xmm reg。然后改变了几个运动指令等等。
我的MMX和SSE代码粘贴在此处: https://gist.github.com/abidrahmank/5281486 (我不想在这里全部粘贴)
稍后从main.cpp文件中调用这些函数,其中数组作为参数传递。
我做了什么:
1 - 我查看了英特尔和其他网站的一些优化手册。 SSE2代码的主要问题是 16 _memory alignment 。当我手动检查地址时,发现它们都是16 _memory对齐的。但我同时使用了 MOVDQU 和 MOVDQA ,但与MMX相比,两者都给出了相同的结果且没有加速。
2 - 我进入调试模式并使用执行的指令检查每个寄存器值。并且它们的执行与我想象的完全相同,即取16个字节并输出16个字节。
资源:
我在Windows 7和Visual C ++ 2010中使用英特尔酷睿i5处理器。
问题:
最后一个问题是,为什么SSE2代码与MMX代码相比没有性能改进?我在SSE代码中做错了吗?或者还有其他解释吗?
答案 0 :(得分:3)
Harold 的评论绝对正确。您正在处理的数组不适合您计算机上的缓存,因此您的计算完全受加载存储限制。
我计算了当前代i7上各种缓冲区长度的计算吞吐量,以及除了加载和存储除外的所有内容的相同例程的吞吐量:
我们在此观察到的是,一旦缓冲区变得如此之大以至于它不在L3缓存中,计算的吞吐量就会与实现的加载/存储带宽完全匹配。这告诉我们如何处理数据基本上没有区别(除非你使它明显变慢);计算速度受处理器向/从内存移动数据的能力的限制。
如果你在较小的阵列上进行计时,你会发现两个实现之间存在差异。