在尝试优化有限差分代码所必需的未对齐读取时,我更改了未对齐负载,如下所示:
__m128 pm1 =_mm_loadu_ps(&H[k-1]);
进入对齐的读取+随机代码:
__m128 p0 =_mm_load_ps(&H[k]);
__m128 pm4 =_mm_load_ps(&H[k-4]);
__m128 pm1 =_mm_shuffle_ps(p0,p0,0x90); // move 3 floats to higher positions
__m128 tpm1 =_mm_shuffle_ps(pm4,pm4,0x03); // get missing lowest float
pm1 =_mm_move_ss(pm1,tpm1); // pack lowest float with 3 others
其中
H
是16个字节对齐的;并且H[k+1]
,H[k±3]
和movlhps
和movhlps
优化对于H[k±2]
(here是循环的完整代码)也有类似的变化。我发现在Core i7-930上读取
H[k±3]
的优化似乎很有效,而为±1
添加下一个优化则减慢了循环速度(以百分比为单位)。在±1
和±3
优化之间切换不会改变结果。同时,在Core 2 Duo 6300和Core 2 Quad上,同时启用优化(针对
±1
和±3
)都提高了性能(提高了百分之几十),而对于Core i7-4765T而言,这两种性能都降低了性能(降低了百分比单位)。在奔腾4上,所有尝试优化未对齐读取的尝试,包括那些使用
movlhps
/ movhlps
的读取都会导致速度降低。为什么对于不同的CPU如此不同?是否因为代码大小增加而导致循环可能不适合某些指令缓存?还是因为某些CPU对读取错误对齐不敏感,而另一些CPU敏感得多?也许在某些CPU上,诸如随机播放之类的动作很慢?
最佳答案
英特尔每两年推出一次新的微体系结构。执行单元的数量可以改变,以前只能在一个执行单元中执行的指令在较新的处理器中可能有2或3个可用。指令的等待时间可能会发生变化,就像添加shuffle
执行单元时一样。
英特尔在其《优化参考手册》中提供了一些详细信息,这是链接,下面已复制了相关章节。
http://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
第3.5.2.7节浮点/ SIMD操作数
来自存储器的MOVUPD指令执行两个64位加载,但是需要额外的μop来调整地址并将这些加载合并到一个寄存器中。使用MOVSD XMMREG1,MEM可以获得相同的功能; MOVSD XMMREG2,MEM + 8; UNPCKLPD XMMREG1,XMMREG2,它使用较少的μop,并且可以更有效地打包到跟踪缓存中。已经发现,在某些情况下,后者可以提供百分之几的性能改进。它的编码需要更多的指令字节,但是对于Pentium 4处理器来说很少有问题。 MOVUPD的存储版本非常复杂且运行缓慢,以至于必须始终使用带有两个MOVSD和一个UNPCKHPD的序列。
汇编/编译器编码规则44。(ML影响,L通用性)对于未对齐的128位负载,不要使用MOVUPD XMMREG1,MEM,而应使用MOVSD XMMREG1,MEM。 MOVSD XMMREG2,MEM + 8; UNPCKLPD XMMREG1,XMMREG2。如果附加寄存器不可用,则使用MOVSD XMMREG1,MEM; MOVHPD XMMREG1,MEM + 8。
汇编/编译器编码规则45。(M影响,ML通用性)代替将MOVUPD MEM,XMMREG1用于存储,请使用MOVSD MEM,XMMREG1; UNPCKHPD XMMREG1,XMMREG1; MOVSD MEM + 8,改为XMMREG1。
第6.5.1.2节数据混乱
从SoA到AoS格式的大量数据可以应用于许多应用程序域,包括3D几何,视频和图像。可以采用两种不同的模糊处理技术来处理浮点数据和整数数据。例6-3说明了使用SHUFPS,MOVLHPS,MOVHLPS指令的Swizzle函数。
例6-3中的技术(使用SHUFPS加载16个字节并复制XMM寄存器的一半)比在较新的微体系结构上使用MOVLPS / MOVHPS加载每个向量的一半的替代方法更可取。这是因为使用MOVLPS / MOVHPS加载8个字节会产生代码依赖性并降低执行引擎的吞吐量。例6-3和例6-4的性能考虑通常取决于每个微体系结构的特性。例如,在Intel Core微体系结构中,执行SHUFPS的速度往往比PUNPCKxxx指令的速度慢。在增强型英特尔®酷睿™微体系结构中,由于具有128位随机播放执行单元,SHUFPS和PUNPCKxxx指令均以1个周期的吞吐量执行。那么下一个重要的考虑因素是,只有一个端口可以执行PUNPCKxxx,而MOVLHPS / MOVHLPS可以在多个端口上执行。由于有3个用于执行SIMD指令的端口,因此两种技术的性能在Intel Core微体系结构上均比以前的微体系结构有所改善。由于采用了128位混洗单元,因此这两种技术在增强型Intel Core微体系结构上均得到了进一步改进。