在英特尔芯片上执行半精度浮点运算是否可能?
我知道如何加载/存储/转换半精度浮点数[1],但我不知道如何在不转换为单精度浮点数的情况下进行加法/乘法运算。
[1] https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats
在英特尔芯片上执行半精度浮点运算是否可能?
我知道如何加载/存储/转换半精度浮点数[1],但我不知道如何在不转换为单精度浮点数的情况下进行加法/乘法运算。
[1] https://software.intel.com/en-us/articles/performance-benefits-of-half-precision-floats
相关: https://scicomp.stackexchange.com/questions/35187/is-half-precision-supported-by-modern-architecture - 关于Cooper Lake和Sapphire Rapids中的BFloat16以及一些非英特尔信息。
Sapphire Rapids将同时支持BF16和FP16,其中FP16使用与F16C转换指令相同的IEEE754二进制16格式,而不是brain-float。AVX512-FP16支持大多数数学运算,而BF16只有转换为/从单精度和点积累加对成单精度的功能。
这也适用于Alder Lake,在禁用E核并在BIOS中专门启用AVX-512的系统上(截至目前,显然还没有官方支持;只有一些主板厂商提供此选项)。
(答案的其余部分未更新,仍涉及Sapphire Rapids / Alder Lake具有FP16 / BF16的情况。)
英特尔芯片是否支持半精度浮点运算?
是的,显然,Skylake及以后版本的芯片中的芯片上GPU硬件支持FP16和FP64,以及FP32。通过足够新的驱动程序,您可以通过OpenCL使用它。
在早期的芯片上,FP16与FP32的吞吐量大致相同(可能只是几乎免费地进行转换),但在SKL / KBL芯片上,GPGPU Mandelbrot的FP32吞吐量大约是FP32的两倍(请注意该链接中Mpix/s轴上的对数刻度)。
Skylake iGPU上FP64(double
)性能的增益也非常巨大。
但是在IA核心(Intel-Architecture)上,甚至使用AVX512也没有硬件支持除将它们转换为单精度之外的任何内容。这可以节省内存带宽,并且如果您的代码瓶颈在内存上,则肯定可以加快速度。但是对于不受内存瓶颈限制的代码,它并不能增加峰值FLOPS。
当然,您可以实现软件浮点运算,可能甚至可以在SIMD寄存器中实现,因此从技术上讲,您提出的问题的答案仍然是“是”,但它不会比使用F16C VCVTPH2PS
/ VCVTPS2PH
指令+打包单精度vmulps
/ vfmadd132ps
硬件支持更快。
在x86代码中使用支持HW的SIMD转换以/从float
/ __m256
来交换额外的ALU转换工作,以减少内存带宽和缓存占用。但是,如果缓存阻塞(例如针对经过良好调整的密集matmul)或非常高的计算强度意味着您没有内存瓶颈,则只需使用float
并节省ALU操作。
bfloat16
(Brain Float)和AVX512 BF16Intel®架构指令集扩展和未来功能编程参考在2019年4月的修订版-036中增加了有关BF16的详细信息,包括它被安排在“未来,库珀湖”中。一旦发布,指令的文档将移至主vol.2 ISA参考手册(以及pdf->HTML爬取https://www.felixcloutier.com/x86/index.html)。
https://github.com/HJLebbink/asm-dude/wiki具有来自vol.2和未来扩展手册的说明,因此您已经可以在那里找到它。
只有三条指令:转换为/从float
,以及BF16乘法+成对累加到float
。(点积的第一步水平)。因此,AVX512 BF16最终提供了真正的16位浮点计算,但仅以这种非常有限的形式将结果转换为float
。
他们还忽略MXCSR,始终使用默认舍入模式和DAZ / FTZ,并且不设置任何异常标志。
VCVTNEPS2BF16 [xxy]mm1{k1}{z}, [xyz]mm2/m512/m32bcst
__m256bh _mm512_cvtneps_pbh (__m512);
其他两个不支持内存错误抑制(使用掩码与内存源操作数一起使用时)。可能是因为掩码是针对目标元素的,而源元素数量不同。显然,将单精度浮点数转换为BF16可以抑制内存错误,因为相同的掩码可以适用于32位源元素和16位目标元素。
VCVTNE2PS2BF16 [xyz]mm1{k1}{z}, [xyz]mm2, [xyz]mm3/m512/m32bcst
ConVerT (No Exceptions) 2 registers of Packed Single 2(to) BF16.
_m512bh _mm512_cvtne2ps_pbh (__m512, __m512);
VDPBF16PS [xyz]mm1{k1}{z}, [xyz]mm2, [xyz]mm3/m512/m32bcst
Dot Product of BF16 Pairs Accumulated into Packed Single Precision
__m512 _mm512_dpbf16_ps(__m512, __m512bh, __m512bh);
(Notice that even the unmasked version has a 3rd input for the destination accumulator, like an FMA).
# the key part of the Operation section:
t ← src2.dword[ i ] (or src.dword[0] for a broadcast memory source)
srcdest.fp32[ i ] += make_fp32(src1.bfloat16[2*i+1]) * make_fp32(t.bfloat[1])
srcdest.fp32[ i ] += make_fp32(src1.bfloat16[2*i+0]) * make_fp32(t.bfloat[0])
所以我们仍然没有得到本地的16位FP数学,您可以在保持数据为16位格式的情况下用于任意事物,每个向量32个元素。只有FMA进入32位累加器。
有一些关于Posit FPU硬件的论文设计,但现在还处于早期阶段,我认为只有FPGA实现已经被构建。一些Intel CPU将配备板载FPGA(或者可能已经是现成的东西)。
截至2019年中期,我没有看到任何商用CPU设计中包含Posit执行单元的报道,谷歌也没有找到任何相关信息。
如果您正在使用所有核心,我认为在许多情况下,您仍然受到内存带宽的限制,使用半精度浮点数将是一个优势。