首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么在某些CPU上,SSE对齐读取+随机洗牌比未对齐读取慢,而在另一些CPU上则不是?

为什么在某些CPU上,SSE对齐读取+随机洗牌比未对齐读取慢,而在另一些CPU上则不是?
EN

Stack Overflow用户
提问于 2014-04-22 15:11:49
回答 2查看 1.4K关注 0票数 3

在尝试优化有限差分代码所需的未对齐读取时,我更改了未对齐加载,如下所示:

代码语言:javascript
复制
__m128 pm1 =_mm_loadu_ps(&H[k-1]);

进入这个对齐的read + shuffle代码:

代码语言:javascript
复制
__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是循环的完整代码)。

我发现在我的Corei7-930上,读取H[k±3]的优化似乎是卓有成效的,而为±1添加next优化则减慢了我的循环(以百分比为单位)。在±1±3优化之间切换不会改变结果。

同时,在酷睿2Duo6300和酷睿2Quad上,启用了这两种优化(针对±1±3)提高了性能(提高了数十%),而对于酷睿i7-4765T,这两种优化都降低了性能(单位为百分比)。

在奔腾4上,所有优化未对齐读取的尝试都会导致速度减慢,包括使用movlhps/movhlps的读取。

为什么不同的CPU会有如此大的不同?是不是因为代码大小的增加,使得循环可能不适合某些指令缓存?或者是因为一些CPU对未对齐的读取不敏感,而其他CPU则敏感得多?或者,也许在一些CPU上,像shuffles这样的动作很慢?

EN

回答 2

Stack Overflow用户

发布于 2014-04-24 04:20:20

每隔两年,英特尔就会推出一种新的微架构。执行单元的数量可以改变,以前只能在一个执行单元中执行的指令在较新的处理器中可能有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节浮点/单指令多数据操作数

内存中的MOVUPD指令执行两个64位加载,但需要额外的μ操作来调整地址并将加载合并到单个寄存器中。可以使用MOVSD XMMREG1,MEM;MOVSD XMMREG2,MEM+8;UNPCKLPD XMMREG1,XMMREG2获得相同的功能,它使用更少的μ操作,可以更有效地打包到跟踪缓存中。已发现后一种替代方案在某些情况下可提供几个百分点的性能改进。它的编码需要更多的指令字节,但这对于奔腾4处理器来说很少是问题。MOVUPD的存储版本复杂且缓慢,以至于应该始终使用具有两个MOVSD和一个UNPCKHPD的序列。

汇编/编译器编码规则44. (ML impact,L generality)对于未对齐的128位加载,使用MOVSD XMMREG1,MEM;MOVSD XMMREG2,MEM+8;UNPCKLPD XMMREG1,XMMREG2。如果附加寄存器不可用,则使用MOVSD;MOVHPD XMMREG1,MEM+8。

汇编/编译器编码规则45. (M impact,ML通用性)代替使用MOVUPD MEM,XMMREG1进行存储,请使用MOVSD MEM,XMMREG1;UNPCKHPD XMMREG1,XMMREG1;MOVSD MEM+8,XMMREG1。

6.5.1.2节Data Swizzling

将数据从SoA格式转换为AoS格式可以应用于许多应用领域,包括3D几何图形、视频和成像。可以采用两种不同的swizzling技术来处理浮点和整数数据。Example 6-3说明了使用SHUFPS、MOVLHPS、MOVHLPS指令的swizzle函数。

示例6-3中的技术(加载16字节,使用SHUFPS并复制XMM寄存器的一半)优于在较新的微体系结构上使用MOVLPS/MOVHPS加载每个向量的一半的替代方法。这是因为使用MOVLPS/MOVHPS加载8个字节会产生代码依赖,并降低执行引擎的吞吐量。实施例6-3和实施例6-4的性能考虑因素通常取决于每个微体系结构的特性。例如,在英特尔酷睿微体系结构中,执行SHUFPS指令往往比执行PUNPCKxxx指令慢。在增强型英特尔酷睿微体系结构中,由于128位混洗执行单元,SHUFPS和PUNPCKxxx指令都以1个周期的吞吐量执行。然后,下一个重要的注意事项是只有一个端口可以执行PUNPCKxxx,而MOVLHPS/MOVHLPS可以在多个端口上执行。由于3个端口用于执行SIMD指令,这两种技术在英特尔酷睿微体系结构上的性能都优于以前的微体系结构。由于128位混洗单元,这两种技术都进一步改进了增强型英特尔酷睿微体系结构。

票数 6
EN

Stack Overflow用户

发布于 2014-04-22 20:30:12

在较旧的CPU上,未对齐的负载会带来很大的性能损失-它们会生成两个总线读取周期,然后在两个读取周期之后进行一些额外的修复。这意味着未对齐的负载通常比对齐的负载慢2倍或更多。然而,对于更新的CPU(例如,核心i7),未对齐负载的惩罚几乎可以忽略不计。因此,如果您需要支持旧CPU和新CPU,那么您可能希望以不同的方式处理未对齐的负载。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23212882

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档