avx512中比较内在指令的不同语义?

Posted

技术标签:

【中文标题】avx512中比较内在指令的不同语义?【英文标题】:Different semantic of comparison intrinsic instructions in avx512? 【发布时间】:2018-01-04 15:59:21 【问题描述】:

使用 sse2 或 avx 比较操作返回全零或全一的位掩码(例如 _mm_cmpge_pd 返回 __m128d。

我找不到 avx512 的等效项。比较操作似乎只返回短位掩码。语义是否发生了根本变化,还是我遗漏了什么?

【问题讨论】:

【参考方案1】:

是的,AVX512 中的语义有点不同。比较指令在掩码寄存器中返回结果。这有几个优点:

(8) 个掩码寄存器与[xyz]mm 寄存器集完全分开,因此您不会为比较结果浪费一个向量寄存器。 几乎整个 AVX512 指令集都有屏蔽版本,让您可以灵活地使用比较结果。

与传统的 SSE/AVX 实现相比,它确实需要稍微不同的代码,但还不错。

编辑:如果你想模仿旧的行为,你可以这样做:

// do comparison, store results in mask register
__mmask8 k = _mm512_cmp_pd_mask(...);
// broadcast a mask of all ones to a vector register, then use the mask
// register to zero out the elements that have a mask bit of zero (i.e.
// the corresponding comparison was false)
__m512d k_like_sse = _mm512_maskz_mov_pd(k, 
    (__m512d) _mm512_maskz_set1_epi64(0xFFFFFFFFFFFFFFFFLL));

可能有一种更优化的方法可以做到这一点,但我自己对使用 AVX512 还是比较陌生。所有的掩码都可以预先计算和重复使用,因此您实际上只是添加了一个额外的掩码移动指令来生成您正在寻找的向量结果。

编辑 2: 正如 Peter Cordes 在下面的评论中所建议的,您可以改用 _mm512_movm_epi64() 来进一步简化上述内容:

// do comparison, store results in mask register
__mmask8 k = _mm512_cmp_pd_mask(...);
// expand the mask to all-0/1 masks like SSE/AVX comparisons did
__m512d k_like_sse = (__m512d) _mm512_movm_epi64(k);

【讨论】:

如果您需要保存中间结果,之前是带有有趣值的双精度向量,现在是单比特向量。这是一场噩梦般的重构!矢量容器大小发生变化。循环剥离逻辑更改。这些位掩码的所有用例都用于执行 x 和 y 等操作,其中 x 是双精度,y 是位掩码,请更改。无论如何,谢谢,这是正确的答案。 是的,我正在考虑类似的事情,至少作为一个临时解决方案。也许用 blend_pd。需要试验什么更有效。 大概是这个:_mm512_maskz_mov_pd @Fabio 这些变化是这种低级编程的不幸代价。但是一旦正确编写,使用这种东西的代码的原始指令数可能会显着下降。主要是因为丢失了所有融合到嵌入式掩码中的按位指令。我在新系统中遇到的唯一问题是掩码寄存器用完。 有一个 AVX512DQ(或窄元素的 AVX512BW)指令用于将 k 掩码转换为 0 / -1 向量:__m512i _mm512_movm_epi64(__mmask16 ) / VPMOVM2Q zmm1, k1。使用它而不是maskz_mov_pd,因此您首先不需要全为常量。或者最好尽可能按照应有的方式使用掩码。

以上是关于avx512中比较内在指令的不同语义?的主要内容,如果未能解决你的问题,请参考以下文章

动态确定恶意 AVX-512 指令的执行位置

给定一个 int 偏移向量,如何使用 AVX512 内在函数收集单个字节?

2 个 AVX-512 向量元素的交错合并 - C 内在

AVX512 缺少内在的 _mm512_round_ps

使用内在函数将双 SSE2/AVX/AVX512 存储为浮点数的最佳方法

发行版将 GCC 升级到 5.5.0 后,AVX512 内在函数头会产生许多错误