3

问题 :

我将 MMX 代码转换为相应的 SSE2 代码。我预计几乎 1.5x-2x 的加速。但两者都花费了完全相同的时间。为什么?

设想:

我正在学习 SIMD 指令集及其性能比较。我进行了一个数组操作,其中 X 和 Y 是"char"Z = X^2 + Y^2类型的大型一维数组。X 和 Y 的值被限制为小于 10,因此 Z 始终<255 (1 Byte)。(不用担心任何溢出)。

我先写了它的 C++ 代码,检查了它的时间。然后编写相应的汇编代码(~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 对齐。当我手动检查地址时,发现它们都是 16 _memory 对齐的。但是我同时使用了MOVDQUMOVDQA,但两者都给出了相同的结果,并且与 MMX 相比没有加速。

2 - 我进入调试模式并检查每个寄存器值并执行指令。它们的执行与我想的完全一样,即占用 16 个字节并输出 16 个字节。

资源 :

我在 Windows 7 和 Visual C++ 2010 中使用 Intel Core i5 处理器。

问题 :

所以最后一个问题是,为什么 SSE2 代码与 MMX 代码相比没有性能提升?我在 SSE 代码中做错了吗?还是有其他解释?

4

1 回答 1

4

哈罗德的评论完全正确。您正在处理的数组不适合您机器上的缓存,因此您的计算完全受负载存储限制。

我对当前一代 i7 上各种缓冲区长度的计算吞吐量进行了计时,还对同一例程的吞吐量进行了计时,但除去了加载和存储之外的所有内容:

吞吐量

我们在这里观察到的是,一旦缓冲区变得如此之大以至于超出了 L3 缓存,您的计算吞吐量与实现的加载/存储带宽完全匹配。这告诉我们,处理数据的方式基本上没有区别(除非您将其显着变慢);计算速度受限于处理器将数据移入/移出内存的能力。

如果您在较小的阵列上进行计时,您将看到两种实现之间的差异。

于 2013-04-01T01:33:06.610 回答