【发布时间】:2011-09-27 18:39:03
【问题描述】:
我一直在尝试优化我使用微软的 sse 内在函数的一些代码。优化我的代码时最大的问题之一是每当我想使用常量时就会发生 LHS。似乎有一些关于生成某些常量的信息(here 和 here - section 13.4),但它都是汇编(我宁愿避免)。
问题是当我尝试用内在函数实现相同的东西时,msvc 抱怨类型不兼容等。有谁知道使用内在函数的任何等效技巧吗?
示例 - 生成 {1.0,1.0,1.0,1.0}
//pcmpeqw xmm0,xmm0
__m128 t = _mm_cmpeq_epi16( t, t );
//pslld xmm0,25
_mm_slli_epi32(t, 25);
//psrld xmm0,2
return _mm_srli_epi32(t, 2);
这会产生一堆关于不兼容类型的错误(__m128 vs _m128i)。我对此很陌生,所以我很确定我错过了一些明显的东西。有人可以帮忙吗?
tldr - 如何生成一个 __m128 vec,其中填充有 ms 内在函数的单精度常量浮点数?
感谢阅读:)
【问题讨论】:
-
是什么让你认为你需要这样做?通常常量只在计算循环之前加载一次,因此内存访问的相对成本可以忽略不计。
-
我有几个常量,所有这些都在一个循环中使用,不幸的是它似乎已经使用了所有 8 个 xmm 寄存器。在 vtune 中,我在使用其中一些常量时得到了非常高的 CPI。我想也许如果我可以减少我正在访问的常量的数量,并生成一些,这可能会降低成本,因为一个会隐藏另一个的成本。此外,奇怪的是,在其中一个常量上使用 register 关键字有很大帮助(即使这只是导致一些其他值被推出 xmm regs)。
-
如果可以,请使用 x86-64 - 这样您可以获得 16 个 XMM 寄存器。另请注意,即使您在第一次加载这些常量时遇到一个或多个缓存未命中,也应该在大量迭代中分摊,其中常量随后将位于 L1 缓存中。 (当然,除非你只有少量的循环迭代?)
-
请注意,一些编译器会在使用前生成一个 pxor 指令,将
t归零,即使您尝试在未初始化的情况下使用它。根据编译器的不同,从_mm_set1_epi16(-1)开始可能会更好,因为编译器知道如何使用 pcmpeq 来做到这一点。还有_mm_undefined_si128(),它就是为这种事情而存在的,但并不是所有的编译器都支持它。例如clang-3.5 没有,但 clang-3.8 有。
标签: c++ optimization sse simd