8

我试图了解在切换执行单元的域时可能会绕过延迟。

例如,以下两行代码给出完全相同的结果。

_mm_add_ps(x, _mm_castsi128_ps(_mm_slli_si128(_mm_castps_si128(x), 8)));
_mm_add_ps(x, _mm_shuffle_ps(_mm_setzero_ps(), x, 0x40));

哪一行代码更好用?

第一行的汇编输出给出:

vpslldq xmm1, xmm0, 8
vaddps  xmm0, xmm1, xmm0

第二行的汇编输出给出:

vshufps xmm1, xmm0, XMMWORD PTR [rcx], 64   ; 00000040H
vaddps  xmm2, xmm1, XMMWORD PTR [rcx]

现在,如果我查看 Agner Fog 的微架构手册,他在第 112 页给出了一个示例,即对浮点值使用整数随机播放 (pshufd) 与对浮点值使用浮点随机播放 (shufps)。切换域会增加 4 个额外的时钟周期,因此使用 shufps 的解决方案更好。

我列出的第一行代码_mm_slli_si128必须在整数和浮点向量之间切换域。第二次使用_mm_shuffle_ps留在同一个域中。这不是意味着第二行代码是更好的解决方案吗?

4

1 回答 1

8

英特尔优化指南中的第 2.1.4 节表明您(和 Agner)在这件事上是完全正确的 -

当一个堆栈中执行的微操作的源来自另一个堆栈中执行的微操作时,可能会出现一个或两个周期的延迟。英特尔 SSE 整数和英特尔 SSE 浮点运算之间的转换也会出现延迟。

在此处输入图像描述

所以总的来说,你最好尽可能地保持在同一个堆栈/域内。

当然,基准测试始终是首选,只有在这确实是代码中的瓶颈时才值得处理所有这些。

于 2013-10-24T19:12:40.607 回答