我有两个__m128i
s, a
and b
,我想进行洗牌,以便高 64 位a
落在低 64 位dst
和低 64 位b
落在上64dst
. i.e.
dst[ 0:63] = a[64:127]
dst[64:127] = b[0:63]
相当于:
__m128i dst = _mm_unpacklo_epi64(_mm_srli_si128i(a, 8), b);
or
__m128i dst = _mm_castpd_si128(mm_shuffle_pd(_mm_castsi128_pd(a),_mm_castsi128_pd(b),1));
有比第一种方法更好的方法吗?第二条指令只有一条指令,但切换到浮点 SIMD 执行比第一条指令的额外指令成本更高。
延迟并不总是最糟糕的事情。如果它不是循环携带的 dep-chain 的一部分,则只需使用单个指令。
而且,也可能没有!阿格纳·福格微架构文档 http://agner.org/optimize/说他在 Sandybridge 上使用“错误”类型的 shuffle 或布尔值时,在某些情况下没有发现额外的延迟。混合仍然有额外的延迟。他表示,在 Haswell 上,混合类型的随机播放根本没有额外的延迟。 (第 140 页,数据旁路延迟。)
所以继续使用shufps
,除非您非常关心您的代码在 Nehalem 上的运行速度。 (以前的设计(merom/conroe 和 Penryn)没有因使用错误的移动或洗牌而产生额外的旁路延迟。)
对于AMD来说,shufps
运行在ivec域中,与整数洗牌相同,所以使用它就可以了。与 Intel 一样,FP 混合在 FP 域中运行,因此 FP 数据没有旁路延迟。
如果您根据支持的指令集包含多个 asm 版本,而不像 x264 那样完全热衷于为每个 CPU 提供最佳版本,那么您可能会在 AVX CPU 的版本中使用错误类型的操作,但使用多个指令在您的非 AVX 版本中。 Nehalem 具有较大的惩罚(每个域转换有 2 个周期旁路延迟),而 Sandybridge 为 0 或 1 个周期。 SnB 是带有 AVX 的第一代。
Nehalem 之前的版本(没有 SSE4.2)太旧了,以至于可能不值得专门为其调整版本,即使它对“错误类型”洗牌没有任何惩罚。 Nehalem 正处于速度有点慢的边缘,因此在这些系统上运行的软件将很难实时运行,或者感觉不慢。因此,对 Nehalem 的不好会增加糟糕的用户体验,因为他们的系统已经不是最快的了。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)