Page 30 - 《软件学报》2025年第12期
P. 30
沈莉 等: swJulia: 面向新一代神威超级计算机的 Julia 语言编译系统 5411
当被@saca 修饰的 Kernel 首次调用时, 由于元编程特性, swJulia 会使用 SACA.jl 中的 CPE 编译器, 将 Kernel
函数编译和链接为 CPE 动态目标码. 当该 Kernel 再次被调用时, 由于动态目标码已被加载到内存, 因此无需再次
执行编译和链接操作, 此时的 Kernel 启动时间与 SACA C 实现的静态 Kernel 调用基本相当. 由于 CPE 代码通常
与 MPE 代码紧耦合, 并且可能依赖于 MPE 代码中的数据类型和函数, 如果 MPE 代码中的数据类型或函数发生
变化, 那么相关的 CPE 代码也需要被重新编译以确保程序的正确性.
与 MPE 编译器支持完备的 Julia 语言语法和特性不同, CPE 编译器仅支持 Julia 语言的部分核心功能, 包括基
本数据类型、数组操作、函数定义、元组和命名元组、结构体、原子操作等. 而对于协程、任务、通道等复杂并
发编程特性, 以及多重分派、抽象类型等高级类型系统特性, 在 CPE 编译器中的使用则会受到限制. 为了确保最
佳性能和兼容性, 用户在编写 SACA Kernel 时应尽量避免复杂的控制流和过多的分支, 同时尽量减少高级数据结
构和算法的使用.
2.3.2 SACA 封装
作为当前编译领域主流的优化方法, 基于向量化的程序变换已得到学术界的广泛研究 [24,25] . SACA.jl 针对
SW26010Pro 的 SIMD 指令集特点, 提供了完备的向量类型扩展. 图 8 所示的向量加法示例中, 每个 CPE 循环执
行 8 次 Float32 类型的标量加法操作, SACA.jl 能够对其进行向量优化, 优化后的 Julia 代码如图 10 所示.
图 10 CPE 编译器实施 SIMD 优化后的 Julia 代码
图 10 中, floatv8 是 SACA.jl 的内建数据类型, 表示分量个数为 8 的 Float32 向量. SACA.jl 支持的 CPE 向量
扩展数据类型在表 2 中进行了详细说明, 其命名方式与 SACA C 保持一致. unsafe_load 及 unsafe_store!接口使用
了元编程技术, 通过@generate 生成针对特定地址空间的 LLVM IR. 这些 IR 会在编译时注入到生成的代码中, 从
而在运行时实现优化的内存访问操作. 最后, CPE 编译器将向量加法操作进行逐个元素展开, 如图 10 中第 11–18
行所示, 以生成 swLLVM 编译器 CPE 后端可识别的向量化的中间表示.
表 2 SACA.jl 支持的 CPE 向量扩展数据类型
类型 含义 分量表示范围
intv16 16×32位有符号整型 –2E31~2E31–1
uintv16 16×32位无符号整型 0~2E32–1
int512 512位有符号长整型 -
uint512 512位无符号长整型 -
floatv8 8×32位单精度浮点 1.175E–38~3.402E38
doublev8 8×64位双精度浮点 2.22E–308~1.79E308
halfv32 32×16位半精度浮点 6.104E–5~65 504

