【问题标题】:Constant floats with SIMD带 SIMD 的常量浮点数
【发布时间】:2011-09-27 18:39:03
【问题描述】:

我一直在尝试优化我使用微软的 sse 内在函数的一些代码。优化我的代码时最大的问题之一是每当我想使用常量时就会发生 LHS。似乎有一些关于生成某些常量的信息(herehere - 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


【解决方案1】:

【讨论】:

  • 0x1a11 251 movaps xmm6, xmmword ptr [0x414890] 0x1a18 251 xorps xmm5, xmm5 嗨,感谢您抽出宝贵时间回答 :) 正如您从 __mm_set_ps 上面的(格式错误,抱歉)列表中看到的那样,它并没有真正帮助我,因为它仍然在使用movaps 从内存中的某处加载常量。我想要的是使用现有方法直接在 xmm 寄存器中生成常量。
  • @JBeFat:您是否尝试过简单地转换结果?这些技巧是使用整数指令来创建浮点值,所以编译器抱怨类型不匹配我并不感到惊讶。
  • 另请注意,没有带有__mm_set_ps 的 LHS 存储,因为不涉及 FPU。
  • 从暖缓存读取时,MOVAPS 实际上在大多数 CPU 上都一样快或更快。此外,在某些(主要是 AMD)处理器上,int/float 转换也会带来一些难以预测的额外延迟。最后,代码太糟糕了。 _mm_set_ps 具有描述性且明确。如果您在 5 年后阅读您的代码,一些奇怪的 bit hack 序列会让您想知道您到底打算在那里做什么。
  • @Ben Voigt:是的,这就是问题所在。引用The microarchitecture of Intel, AMD and VIA CPUs: “XMM 寄存器有一些标签位,用于记住浮点值是正常、非正常还是零。当整数指令的输出为用作单精度或双精度浮点指令的输入。这会导致所谓的重新格式化延迟。”
【解决方案2】:

只需使用_mm_castsi128_ps 将 __m128i 转换为 __m128。另外,第二行应该是

t = _mm_slli_epi32(t, 25)

【讨论】:

  • 谢谢!我有一种感觉,它会像那样简单。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-09-23
  • 1970-01-01
相关资源
最近更新 更多