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
   25   26   27   28   29   30   31   32   33   34   35