【问题标题】:"Extend" data type size in SSE registerSSE 寄存器中的“扩展”数据类型大小
【发布时间】:2013-01-21 09:02:25
【问题描述】:

我正在使用 VS2005(在工作中)并且需要执行以下操作的 SSE 内在函数:

我有一个预先存在的__m128i n 填充了 16 位整数 a_1,a_2,....,a_8

由于我现在想做的一些计算需要 32 位而不是 16 位,我想从 n 中提取两个四组 16 位整数并将它们放入两个分开的 @987654325 @s 分别包含 a_1,...,a_4a_5,...,a_8

我可以使用各种 _mm_set 内在函数手动执行此操作,但这些会导致汇编中有八个 movs,我希望有更快的方法来执行此操作。

【问题讨论】:

  • 看看这些SSE4.1 intrinsics。你可以通过使用其中的两个和一个 unpack/shuffle 来得到你想要的。
  • 我认为它们在 VS2005 中不可用。
  • Eek... VS2005。告诉你的老板烧掉它……用火烧掉。 :)
  • 否则......你会被一堆乱七八糟的洗牌、轮班和面具困住。

标签: c sse simd


【解决方案1】:

假设我正确理解了您想要实现的目标(将一个向量中的 8 x 16 位解压缩为两个 4 x 32 位整数的向量),我通常在 SSE2 及更高版本中这样做:

__mm128i v = _mm_set_epi16(7, 6, 5, 4, 3, 2, 1, 0);  // v = { 7, 6, 5, 4, 3, 2, 1, 0 }
__mm128i v_lo = _mm_srai_epi32(_mm_unpacklo_epi16(v, v), 16); // v_lo = { 3, 2, 1, 0 }
__mm128i v_hi = _mm_srai_epi32(_mm_unpackhi_epi16(v, v), 16); // v_hi = { 7, 6, 5, 4 }

【讨论】:

  • 很好...这并不像我想象的那么糟糕。当然,我从来没有努力过,因为我通常可以访问 SSE4.1。
  • 但这会比 v_lo= _mm_set_epi32(a_1,...,a_4) v_hi = _mm_set_epi32(a_5,a_6,a_7,a_8) 快吗?我可以通过 __m128i 内在函数访问单个值,这似乎是一个联合体,我可以在其中访问各种包含的数据类型,如数组。
  • @TravisG 一切都将比使用_mm_set 和提取单个组件更快。您的代码要做的是将这些值从 SSE 寄存器中取出到一些对齐的内存存储中,对它们中的每一个执行一些非 SSE 操作,然后将其加载到另一个寄存器中。这将比使用一堆 SEE 操作在 SSE 寄存器之外执行所有操作要慢得多。一般来说,从 SSE 寄存器访问单个组件对于任何 SSE 代码都是性能杀手,无论您的库是否通过提供联合来轻松实现可编程......
  • @TravisG ...这并不是说您松散了 SIMD 并行性。这整个单个组件的访问必须由一堆内存操作来支持,因为 SSE 不是为此而构建的。
  • @TravisG:除了 Christian 的有效 cmets,我只想说上面的代码虽然看起来很糟糕,但只能转换为 4 条指令。如果您开始使用标量代码处理单个向量元素,那么您将看到超过 4 条指令(加上所有其他上述问题)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-13
  • 1970-01-01
  • 2011-03-12
相关资源
最近更新 更多