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的主要内容,如果未能解决你的问题,请参考以下文章
使用内在函数将双 SSE2/AVX/AVX512 存储为浮点数的最佳方法
使用 AVX512 或 SVML 内在函数将压缩的 16 位整数与掩码相除