AVX 512 缺少内在 _mm512_round_ps

instrinsic _mm512_round_ps is missing for AVX512

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

什么是好的解决方法?

谢谢!

TL:DR: AVX512F

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

相关:AVX512DQ_mm512_reduce_pd or _ps will subtract the integer part (and a specified number of leading fraction bits), range-reducing your input to only the fractional part. asm docs for vreducepd最详细


EVEX 前缀允许覆盖默认舍入方向 ,用于 FP 指令。 (这就是内在函数的 ..._round_ps() 版本的用途。)但它没有 "round to integer" 选项;你仍然需要一个单独的 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 参考手册没有提到签名,所以我倾向于无符号是最有可能的。

该字段的低 4 位指定与 roundps 类似的舍入模式。和往常一样,指令 has the diagramPD 版本(因为它按字母顺序排在第一位)。

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

(我很好奇 AVX512 CPU 上的 SSE 或 VEX roundpd 是否会根据高 4 位进行缩放;它说它们是 "reserved" 而不是 "ignored"。但可能不是。)


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

合并屏蔽 + SAE 覆盖版本是 __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,向上、向下或截断为零,或通常最接近的even-as-tiebreak 这是 IEEE 默认的舍入模式。或者 _MM_FROUND_CUR_DIRECTION 使用当前模式。 _MM_FROUND_NO_EXC 禁止在 MXCSR 中设置不准确的异常位。


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

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

因此在 imm8 中拥有舍入控制使得vrndscaleps zmm0{k1}, [rdi]{m32bcst}, imm8可以从内存广播一个浮点数,舍入它,并根据掩码寄存器将其合并到现有寄存器中k1 .所有这些都在一条指令中,假设它与 vroundps 相同,在 SKX 上解码为大约 3 微指令。 (http://agner.org/optimize/).