Julia 1.10 正式发布

经过 3 个 beta 版本和 3 次候选发布版本后,Julia 1.10 现已正式发布。这是一种通用的高性能语言,在科学计算和数值分析中较为流行。

新版本的一些亮点内容如下:

将之前用 Scheme 编写的默认解析器替换为用 Julia 编写的新解析器,称为JuliaSyntax.jl。此更改引入了多项改进:提高解析性能、详细的语法错误消息、高级源代码映射。

这项工作主要是通过分析和改进 OmniPackage.jl 的加载时间来完成的,OmniPackage.jl 是一个人造的"mega package",其唯一目的就是依赖和加载大量的依赖项。总的来说,OmniPackage.jl 最终会加载大约 650 个软件包,其中许多软件包都非常大。

随着 Julia 1.10 的改进,堆栈跟踪现在更加简洁:

此更新导致堆栈跟踪更短且更易于阅读。

在 1.10 版中对垃圾收集器(GC)的标记阶段进行了并行化处理,并引入了与应用线程同时运行部分清扫阶段的可能性。这大大加快了多线程分配繁重工作负载的垃圾回收时间。

多线程 GC 可通过命令行选项 –gcthreads=M 启用,该选项可指定在 GC 的标记阶段使用的线程数。也可以通过 –gcthreads=M,1 启用上述并发页面扫描,这意味着在 GC 标记阶段将使用 M 个线程,而一个 GC 线程负责与应用程序同时执行部分扫描阶段。

默认情况下,GC 线程数设置为计算线程数(–threads)的一半。

Julia 1.10 版本使用 LLVM 15。这带来了新处理器和一般现代化更新的配置文件。特别值得注意的是新的 pass-manager 的迁移,有望改进编译时间。LLVM 15 改进了对 x86 上 Float16 的支持。

升级到 LLVM 15 后,可以在 Linux 的 aarch64 CPU 上使用 JITLink。这种 linker 最初是在 Julia v1.8 中引入的,仅适用于 Apple Silicon(macOS 上的 aarch64 CPU),它解决了在该平台上影响 Julia 的频繁 segmentation fault 问题。不过,由于 LLVM 内存管理器中的一个错误,非重要工作负载可能会生成过多的内存映射 (mmap),从而超出允许映射的上限。如果遇到这个问题,可阅读有关如何更改mmap限制的文档。

通过在 LLVM 编译阶段 exposing 并行性,加速了Ahead-of-time compilation (AOT)。现在,编译工作不再是编译一个大型的整体编译单元,而是分成多个小块。这种多线程方式加快了 system images 和大型 package images 的编译速度,从而缩短了其预编译时间。

可以通过环境变量 JULIA_IMAGE_THREADS=n 来控制并行的使用量。此外,由于 Windows 本地 COFF 二进制文件的限制,在 Windows 上编译大型 images 时,多线程将被禁用。

1.10 引入了一种“pidfile”(process id file)锁定机制,该机制可确保只有一个 Julia 进程能够预编译给定的缓存文件,而缓存文件是预编译过程中针对特定 Julia 设置的。

这种安排既有利于可能同时运行多个进程的本地用户,也有利于可能在同一共享仓库中运行数百个工作程序的高性能计算用户。

虽然 Pkg 会在安装后自动并行预编译依赖包,但在使用/导入时进行的预编译以前是串行的,每次预编译一个依赖包。

当用户开发一个软件包时,最终可能会在加载时进行预编译,而且如果开发的软件包中的代码变更深入到正在加载的软件包的依赖关系树中,串行预编译过程可能会特别慢。

1.10 引入了加载时的并行预编译,以捕捉这些情况并加快预编译速度。

更多详情可查看官方公告。