在 OpenCL 3.0 临时版本发布六年后,Khronos Group 现已正式发布了 OpenCL 3.1,将之前作为扩展或可选功能实现的成熟功能整合到了 OpenCL 核心规范中。

所有符合 OpenCL 3.1 标准的实现都必须支持 SPIR-V 内核。SPIR-V 是 Khronos 的可移植中间表示形式,由包括 Clang/LLVM、SPIR-V LLVM 转换器和更新的 SPIR-V LLVM 后端在内的多种开源编译器生成。除了增强源代码语言的灵活性之外,SPIR-V 还允许内核以预编译、优化的中间形式而非源代码形式分发——从而保护内核知识产权、缩短应用程序启动时间并实现提前特化。
OpenCL 3.1 还要求支持 SPIR-V 查询扩展,该扩展使应用程序能够枚举设备支持的 SPIR-V 功能、扩展和版本,从而简化新 SPIR-V 功能的采用。
OpenCL 工作组主席 Neil Trevett 称,“强制集成 SPIR-V 是 OpenCL 3.1 中最具深远意义的改变。SPIR-V 已成为越来越多高级语言和框架(包括 SYCL、ChipStar 以及各种领域特定编译器)的自然编译目标。确保所有符合规范的实现都具备集成 SPIR-V 的能力,消除了这些工具完全采用 OpenCL 作为运行时环境的最后一个障碍。结合工作组的‘扩展优先’方法(该方法确保了 3.1 版本中强制要求的所有功能目前都已投入使用),OpenCL 3.1 进一步增强了现代异构计算所需的可靠、可移植的运行时基础架构。”
高性能计算和 AI 内核的几个关键特性现在也成为 OpenCL 3.1 核心规范的强制性要求:
- Subgroups,包括 shuffles、rotations 以及扩展支持的数据类型集。是优化归约、扫描和矩阵核的基本构建模块。
- 整数点积(包括饱和和累加变体)以及扩展位运算:两者都直接映射到各类现代芯片上的专用硬件指令,并且都是矩阵乘法和推理工作负载核心的低精度算术的常用构建模块。
- 针对建议的本地工作组大小的新查询。这为应用程序和性能分析器提供运行时提示,以确定给定内核和设备的最佳工作组大小,从而无需手动调整或在多个队列中重复计算大小,并提高在各种硬件上的性能可预测性。
- 标准的设备 UUID 查询,与 Vulkan 的 VkPhysicalDeviceIDProperties::deviceUUID 相对应。这使得应用程序能够跨 API 关联同一物理设备,这对于多设备系统以及跨越 OpenCL 和 Vulkan 的外部内存共享场景至关重要。
OpenCL 3.1 还包含一些改进,可以提升日常开发效率:
- 开发者无需依赖扩展即可使用新的语言特性。这意味着内核代码更简洁、更易于移植,能够在所有符合规范的实现中可靠地编译,而无需特定于供应商的扩展保护。
- OpenCL C 的 printf 函数实现现在支持 z (size_t) 和 t (ptrdiff_t) 长度修饰符。这弥合了与标准 C 之间长期存在的移植性差距,使得设备端调试输出能够正确格式化指针大小和差值类型的值,而无需进行类型转换或使用格式化字符串等变通方法。
- CL_DEVICE_HOST_UNIFIED_MEMORY 的语义已得到明确,现可用于区分集成 GPU 与独立 GPU。应用程序现在可以可靠地使用此标志在运行时选择内存分配策略——例如,在主机和设备共享同一物理内存的集成 GPU 上,跳过显式缓冲区复制。
- 可以将本地内存内核参数设置为零,以表明不需要本地内存。这样,对于那些不需要本地内存的配置,即使内核偶尔会使用本地内存,也可以无需单独的代码路径来分发这些内核。
- 现在,事件状态为 CL_COMPLETE 即为同步点,无需再像以前那样显式等待。这消除了一个不易察觉的正确性风险,即轮询事件状态的代码可能与内存可见性发生竞争,从而使事件驱动的同步更加简单且形式上更安全。
- 内存模型的“inclusive scopes”规则已放宽,作用域不再需要完全匹配。这意味着更细粒度的作用域现在可以满足更粗粒度的同步需求。
目前已有多个厂商正在开发对 OpenCL 3.1 的支持,包括 Mesa 驱动程序和 Rusticl。此外,还有作为 Mesa 项目一部分的 Rusticl、PoCL 和 CLVK 等开源实现方案。
公告还提到,针对低开销可重放工作负载的命令缓冲区、统一共享内存的改进、协作矩阵运算以及适用于低精度格式的全新 AI 数据类型,相关扩展功能也即将推出。
除了扩展之外,该工作组还在积极探索 OpenCL 作为更高级别编程模型的基础、在安全关键型市场以及在包括 NPU 和 RISC-V 加速器在内的新兴设备类别中的作用。