最好的方法是将两个__m128i的64位部分混洗

时间:2014-08-13 18:37:48

标签: intel sse simd intrinsics

我有两个__m128i s,ab,我想要混淆,以便a的高64位落在dst的低64位{1}} b的低64位落在dst的高64位。即

dst[ 0:63]  = a[64:127]
dst[64:127] = b[0:63]

相当于:

__m128i dst = _mm_unpacklo_epi64(_mm_srli_si128i(a, 8), b);

__m128i dst = _mm_castpd_si128(mm_shuffle_pd(_mm_castsi128_pd(a),_mm_castsi128_pd(b),1));

有没有比第一种方法更好的方法呢?第二个只是一条指令,但切换到浮点SIMD执行比第一条指令的额外指令更昂贵。

1 个答案:

答案 0 :(得分:1)

延迟并不总是最糟糕的事情。如果它不是循环携带的dep链的一部分,那么只需使用单个指令。

此外,可能没有! Agner Fog的microarch doc说他在使用"错误"时发现在某些情况下没有额外的延迟。 Sandybridge上的shuffle或boolean类型。混合仍然具有额外的延迟。在Haswell,他说混合类型的洗牌没有额外的延迟。 (第140页,数据旁路延迟。)

所以继续使用shufps,除非你非常关心你的代码在Nehalem上的速度很快。 (之前的设计(merom / conroe和Penryn)在使用错误的移动或随机播放方面没有额外的旁路延迟。)

对于AMD,shufps在ivec域中运行,与整数shuffle相同,因此可以使用它。与英特尔一样,FP混合物在FP域中运行,因此FP数据没有旁路延迟。

如果您根据支持的指令集包含多个asm版本,而不必完全了解x264等每个CPU的最佳版本,那么您的版本可能会在AVX CPU中使用错误类型的操作,但是在非AVX版本中使用多个指令。 Nehalem有很大的惩罚(每个域转换有2个周期旁路延迟),而Sandybridge是0或1个周期。 SnB是AVX的第一代产品。

Pre-Nehalem(没有SSE4.2)太老了,可能不值得为它专门调整版本,即使它没有对#34;错误的类型&#进行任何处罚34;洗牌。 Nehalem正处于有点慢的尖端,因此在这些系统上运行的软件将是最难以实时操作的,或者感觉不慢。因此,在Nehalem上做坏事会增加糟糕的用户体验,因为他们的系统已经不是最快的了。