AVX512 缺少内在的 _mm512_round_ps

Posted

技术标签:

【中文标题】AVX512 缺少内在的 _mm512_round_ps【英文标题】:instrinsic _mm512_round_ps is missing for AVX512 【发布时间】:2018-06-14 10:10:53 【问题描述】:

我缺少 AVX512 的内在 _mm512_round_ps(它仅适用于 KNC)。知道为什么这不可用吗?

什么是好的解决方法?

对上下半部分应用_mm256_round_ps并融合结果?

使用_mm512_add_round_ps,一个参数为零?

谢谢!

【问题讨论】:

可能_mm512_cvtps_epi32 是您所需要的。该值根据当前的舍入模式进行舍入。输出是一个压缩整数。您可以使用_mm512_cvtepi32_ps 将其转换回压缩浮点数。 @wim 谢谢,这适用于不超过 32 位整数范围的浮点数,但对于较大的指数,我无法将舍入浮点数压缩为 32 位整数。 我明白了。我有另一个想法,但我必须做一些测试,看看它是否有效。 @wim:我正在写一个解释_mm512_roundscale_ps 的答案,它是roundps 的AVX512 替代品。不过,它被搁置了,很快就会完成。 @PeterCordes 太好了!直到现在我才知道_mm512_roundscale_ps 【参考方案1】:

TL:DR: AVX512F

__m512 nearest_integer = _mm512_roundscale_ps(input_vec, _MM_FROUND_TO_NEAREST_INT|_MM_FROUND_NO_EXC);

相关:AVX512DQ _mm512_reduce_pd_ps 将减去整数部分(以及指定数量的前导小数位),将您的输入范围缩小到仅小数部分。 asm docs for vreducepd 最详细。


EVEX 前缀允许覆盖默认舍入方向er and setting suppress-all-exceptions sae,用于 FP 指令。 (这就是 ..._round_ps() 版本的内在函数的用途。)但它没有“四舍五入”选项;你仍然需要一个单独的 asm 指令。


vroundps xy, xy/mem, imm8 没有升级到 AVX512。实际上确实如此:对于 EVEX 版本,相同的操作码有一个新的助记符,使用在 SSE 和 VEX 编码中保留的立即数的高 4 位。

vrndscaleps xyz, xyz/mem/m32broadcast, imm8 可用于 ss/sd/ps/pd 风格。 imm8 的高 4 位指定要舍入到的小数位数。在这些术语中,四舍五入到最接近的整数就是四舍五入到 0 小数位。舍入到最接近的 0.5 将舍入到 1 个小数位。这与按 2^M 缩放相同,四舍五入到最接近的整数,然后缩小(没有溢出)。

我认为该字段是无符号的,因此您不能使用 M=-1 舍入为偶数。 ISA ref 手册没有提到签名,所以我倾向于 unsigned 是最有可能的。

字段的低 4 位指定舍入模式,如 roundps。像往常一样,指令has the diagram 的PD 版本(因为它按字母顺序排列)。

高 4 位 = 0,它的行为与 roundps 相同:它们对低 4 位使用相同的编码。 指令具有相同的操作码并非巧合,只是前缀不同。

(我很好奇 AVX512 CPU 上的 SSE 或 VEX roundpd 是否真的会根据高 4 位进行扩展;它说它们是“保留”而不是“忽略”。但可能不会。)


__m512 _mm512_roundscale_ps( __m512 a, int imm); 是简洁的内在属性。见Intel's intrinsic finder

merge-masking + SAE-override 版本是__m512 _mm512_mask_roundscale_round_ps(__m512 s, __mmask16 k, __m512 a, int imm, int sae);。不过,sae 操作数没有什么可以做,而 roundscale 已经不能用它的imm8 做,所以它有点毫无意义。

您可以使用 _MM_FROUND_TO_NEAREST_INT |_MM_FROUND_NO_EXC 等常量 documented for _mm_round_pd / _mm256_round_pd,向上、向下或截断至零,或通常最接近的值,即 IEEE 默认的 even-as-tiebreak舍入模式。或_MM_FROUND_CUR_DIRECTION 使用当前模式。 _MM_FROUND_NO_EXC 禁止在 MXCSR 中设置不精确的异常位。


您可能想知道为什么 vrndscaleps 需要任何直接位来指定舍入方向,而您可以使用 EVEX 前缀来覆盖舍入方向 vrndscaleps zmm0 k1, zmm1, rz-sae(或任何正确的语法; NASM 似乎不接受我找到的任何示例。)

答案是显式舍入仅适用于 512 位向量或标量,并且仅适用于寄存器操作数。 (它重新利用了 3 个 EVEX 位,用于设置向量长度(如果支持 AVX512VL),并区分广播内存操作数与向量。EVEX 位根据上下文重载,以将更多功能打包到有限的空间中。)

因此,在 imm8 中具有舍入控制使得 vrndscaleps zmm0k1, [rdi]m32bcst, imm8 可以从内存中广播浮点数,对其进行舍入,然后根据掩码寄存器 k1 将其合并到现有寄存器中。假设它与vroundps 相同,全部在一条指令中解码到可能在 SKX 上 3 微秒。 (http://agner.org/optimize/)。

【讨论】:

非常感谢,这解决了我的问题。我对英特尔内部指南有点困惑:有_mm512_roundscale_ps()_mm512_roundscale_round_ps()。在后者中,可以在附加参数rounding 中指定舍入模式,但imm[0:1] 提供相同的信息? @Ralf:是的,我在回答中提到了这一点:“但是,对于圆形刻度已经无法使用它的 imm8 的 sae 操作数,你无能为力,所以有点毫无意义。”它似乎只是为了统一。 我的意思是:rounding_mm512_roundscale_round_ps() 中覆盖imm[0:1] 吗? @Ralf:如果 imm[2] 未设置,则 imm[1:0] 优先于其他任何内容。但是如果设置了 (#define _MM_FROUND_CUR_DIRECTION 0x4),文档声称它使用 MXCSR.RC,并且没有提到 ER-SAE 舍入模式覆盖。如果 EVEX 前缀提供了 MXCSR.RC 的有效值,如果您使用覆盖,我不会感到惊讶,尽管文档说了什么。好问题。

以上是关于AVX512 缺少内在的 _mm512_round_ps的主要内容,如果未能解决你的问题,请参考以下文章

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

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

使用 AVX512 或 SVML 内在函数将压缩的 16 位整数与掩码相除

_mm512_dpbusd_epi32 AVX-512VNNI 指令的 AVX-512BW 仿真

AVX-512:_mm512_load 与标准指针转换?

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