GSoC 2024:LLVM libc 中的半精度浮点数
C23 定义了新的浮点数类型,例如 _Float16
,它对应于 IEEE Std 754 中的 binary16 格式,也称为“半精度”或 FP16。C23 还相应地定义了 C 标准库的数学函数的新变体,例如 fabsf16
用于获取 _Float16
的绝对值。
“LLVM libc 中的半精度浮点数”Google Summer of Code 2024 项目旨在在 LLVM libc 中实现这些新的 _Float16
数学函数,使其成为第一个已知的实现这些 C23 函数的 C 标准库实现。
我们将数学函数分为两类:基本运算和高级数学函数。LLVM libc 中数学函数的当前实现状态可以在 https://libc.llvm.org/math/index.html#implementation-status 查看。
该项目的具体目标是
- 正确设置生成的标头,以便
_Float16
类型和_Float16
函数可以在各种编译器和架构上使用。 - 为支持的架构添加
_Float16
基本运算的通用实现。 - 尽可能地为特定架构添加
_Float16
基本运算的优化实现,使用专用硬件指令和编译器内置函数。 - 尽可能地添加
_Float16
高级数学函数的通用实现。我们知道我们没有足够的时间来实现所有这些函数。
已完成的工作
- 现在可以在生成的标头中使用
_Float16
类型,并且_Float16
数学函数的声明使用#ifdef
保护生成,以便在支持它们时启用它们。 - 所有 70 个计划的
_Float16
基本运算都已合并。 _Float16
、float
和double
变体的各种基本运算在某些架构上已得到优化。- 在 54 个计划的
_Float16
高级数学函数中,有 8 个已合并,9 个有开放的拉取请求。
我们遇到了意外问题,例如
- Clang 11 中的错误,Clang 11 当前仍受 LLVM libc 支持,并在提交后 CI 中使用。
- 某些提交后 CI 工作者拥有旧版本的编译器运行时,这些运行时在某些架构上缺少一些浮点转换函数。
- 浮点转换函数在编译器运行时供应商(GCC 的 libgcc 和 LLVM 的 compiler-rt)和 CPU 架构之间的行为不一致。
由于这些问题,LLVM libc 目前只在 x86-64 Linux 上启用了所有 _Float16
函数。一些在 AArch64 上被禁用,因为 Clang 11 有错误,所有这些在 32 位 Arm 和 RISC-V 上被禁用,因为编译器运行时存在问题。一些在 GPU 上不可用,因为它们接受 _Float128
参数,而 _Float128
类型在 GPU 上不可用。
目前正在进行工作以通过使用我们自己的浮点转换函数来解决编译器运行时问题。
待完成的工作
- 实现剩余的
_Float16
高级数学函数。 - 在 LLVM libc 将其最低支持的 Clang 版本提升后,启用在 AArch64 上禁用的
_Float16
数学函数。 - 在解决编译器运行时问题后,在 32 位 Arm 和 RISC-V 上启用
_Float16
数学函数。
致谢
我要感谢我的 Google Summer of Code 导师 Tue Ly 和 Joseph Huber,以及我与之互动过的其他 LLVM 维护者,感谢他们的帮助。我还要感谢 Google 组织了这个项目。