Intel芯片上的半精度浮点运算

Half-precision floating-point arithmetic on Intel chips

是否可以在Intel芯片上进行半精度浮点运算?

我知道如何 load/store/convert 半精度浮点数 [1] 但我不知道如何 add/multiply 它们而不转换为单精度浮点数。

[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 binary16 格式,而不是大脑浮动。并且 AVX512-FP16 支持大多数数学运算,不像 BF16 只是将 to/from 单和点积累加对转换为单精度。

这也适用于 Alder Lake,在禁用了 E 内核并在 BIOS 中专门启用了 AVX-512 的系统上(apparently isn't officially supported 截至目前;只有一些主板供应商有此选项。)

(其余答案未针对具有 FP16 / BF16 的 Sapphire Rapids / Alder Lake 进行更新。)


使用片上 GPU

Is it possible to perform half-precision floating-point arithmetic on Intel chips?

是的,显然 Skylake 和更高版本中的片上 GPU 具有对 FP16 和 FP64 以及 FP32 的硬件支持。使用足够新的驱动程序,您可以通过 OpenCL 使用它。

在较早的芯片上,FP16 与 FP32 的吞吐量大致相同(可能只是即时转换几乎免费),但 on SKL / KBL chips you get about double the throughput of FP32 对于 GPGPU Mandelbrot (请注意 link 中图表 Mpix/s 轴上的对数刻度。

在 Skylake iGPU 上,FP64 (double) 性能的提升也是巨大的。


使用 AVX/AVX-512 指令

但是在 IA 内核(英特尔架构)上没有;即使使用 AVX512,也没有任何硬件支持,只能将它们转换为单精度。这节省了内存带宽,如果您的代码在内存上出现瓶颈,当然可以加快速度。但是对于没有内存瓶颈的代码,它不会获得峰值 FLOPS。

您当然可以实现软件浮点,甚至可能在 SIMD 寄存器中,因此从技术上讲,对于您提出的问题,答案仍然是“是”,但它不会比使用 F16C 更快 VCVTPH2PS / VCVTPS2PH 指令 + 打包单 vmulps / vfmadd132ps 硬件支持。

在 x86 代码中使用硬件支持的 SIMD 转换 to/from float / __m256 来交换额外的 ALU 转换工作以减少内存带宽和缓存占用空间。 但是,如果缓存阻塞(例如,对于调整良好的密集 matmul)或非常高的计算强度意味着您没有内存瓶颈,那么只需使用 float 并节省 ALU 操作。


即将推出:bfloat16 (Brain Float) 和 AVX512 BF16

已为神经网络用例开发了一种新的 16 位 FP 格式,其指数范围与 IEEE binary32 相同。与 x86 F16C 转换指令使用的 IEEE binary16 相比,它的有效位数精度要低得多,但显然神经网络代码更关心大指数范围的动态范围。这允许 bfloat 硬件甚至不必费心支持次正规。

一些即将推出的 Intel x86 CPU 内核将具有硬件支持此格式。主要用例仍然是专用的神经网络加速器 (Nervana) 和 GPGPU 类型的设备,但硬件支持的转换至少非常有用。

https://en.wikichip.org/wiki/brain_floating-point_format 有更多细节, 具体来说,Cooper Lake Xeon 和 Core X CPUs 预计将支持 AVX512 BF16.

我还没有看到 Ice Lake(Sunny Cove 微架构)提到它。这两种方式都可以,我不想猜测。

Intel® Architecture Instruction Set Extensions and Future Features Programming Reference revision -036 in April 2019 added details about BF16, including that it's slated for "Future, Cooper Lake". Once it's released, the documentation for the instructions will move to the main vol.2 ISA ref manual (and the pdf->HTML scrape at https://www.felixcloutier.com/x86/index.html).

https://github.com/HJLebbink/asm-dude/wiki 包含第 2 卷和未来扩展手册中的说明,因此您可以在那里找到它。

只有3条指令:转换to/fromfloat和一个BF16乘法+成对累加到float。 (点积的第一个水平步长。)因此 AVX512 BF16 确实 最终提供了 16 位浮点数的真实计算,但仅以这种非常有限的形式将结果转换为 float.

他们也忽略 MXCSR,始终使用默认的舍入模式和 DAZ/FTZ,并且不设置任何异常标志。

另外两个不支持内存故障抑制(当对内存源操作数使用掩码时)。大概是因为屏蔽是针对每个目标元素的,并且源元素的数量不同。将 转换为 BF16 显然可以抑制内存错误,因为相同的掩码可以应用于 32 位源元素作为 16 位目标元素。

  • VCVTNE2PS2BF16 [xyz]mm1{k1}{z}, [xyz]mm2, [xyz]mm3/m512/m32bcst
    ConVerT(无例外)打包单 2(至)BF16 的 2 个寄存器。
    _m512bh _mm512_cvtne2ps_pbh (__m512, __m512);

  • VDPBF16PS [xyz]mm1{k1}{z}, [xyz]mm2, [xyz]mm3/m512/m32bcst
    BF16 对的点积累加到压缩单精度
    __m512 _mm512_dpbf16_ps(__m512, __m512bh, __m512bh);(请注意,即使是未屏蔽版本也有目标累加器的第三个输入,如 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 位累加器。


顺便说一句,sign/exponent/significand 还有其他不基于固定宽度字段的 IEEE-754 结构的实数格式。 Posit 越来越受欢迎。 https://en.wikipedia.org/wiki/Unum_(number_format), Beating Floating Point at its Own Game: Posit Arithmetic, and https://posithub.org/about

他们没有将整个有效数编码 space 用于 NaN,而是将其用于锥形/渐变溢出,支持更大的范围。 (并且删除 NaN 简化了 HW)。 IEEE 浮点数仅支持逐渐 underflow(具有次正规),硬溢出到 +-Inf。 (这在实际数值模拟中通常是一个error/problem,与NaN差别不大。)

The Posit encoding 是一种可变宽度指数,使精度接近 1.0。目标是允许在更多情况下使用 32 位或 16 位精度(而不是 64 位或 32 位),同时仍能获得对科学计算/HPC 有用的结果,例如气候建模。每个 SIMD 向量的工作量加倍,内存带宽减半。

已经有一些针对 Posit FPU 硬件的纸面设计,但仍处于早期阶段,我认为只有 FPGA 实现才真正构建。一些英特尔 CPU 将配备板载 FPGA(或者这可能已经成为现实)。

截至 2019 年年中,我还没有读到任何作为商业 CPU 设计一部分的 Posit 执行单元,并且 google 没有找到任何东西。

如果您使用所有内核,我认为在许多情况下您仍然受内存带宽限制,半精度浮点数将是一个胜利。