page contents

Julia 1.7版本发布,新特性一览

经过 4 个测试版和 3 个候选版本,Julia 1.7 版终于发布了!

attachments-2021-12-afLCWwp661b006737e29f.png

经过 4 个测试版和 3 个候选版本,Julia 1.7 版终于发布了!

  • 新的 RNG

  • 新的线程功能

  • 包管理器

  • Property Destructuring

  • 支持苹果芯片

新的RNG

从第一个版本开始,Julia 就使用流行的 Mersenne Twister 算法作为其默认的随机数生成器。我们知道我们可能会在某个时候重新评估这个选择,但直到 Chet Hega指出通过改变算法我们不仅可以获得明显加速,而且还可以使随机数流可重现之前,这似乎都不是一个需要紧急解决的问题。

Mersenne Twister 以周期特别长而闻名,但这需要相应的大状态,对于任何实际应用来说并不是真正必要的。我们还使用线程本地 RNG 状态来保证线程安全,这会带来一些新的开销来使随机流与任务计划相关。Chet 的提议利用了Xoshiro256 系列 RNG 小得多的状态,在每个任务中放置一个状态,并在每个任务创建时分叉它。这使得随机数仅取决于程序的任务生成结构,而不取决于并行执行计划。

新的线程功能

最近的几个版本对于 Julia 中要求多线程的程序来说非常重要,此版本也不例外:我们解决了运行时中的大量竞争条件,追查了同步错误,改进了对多线程调度工作负载的支持,使默认的随机数生成器对线程更加友好,并添加了原子作为原始语言功能!

添加了对可变结构字段的原子访问的支持,以提供更高效的构建块,通过一组@atomic宏及其相应的通用函数处理线程。这项工作基于“原子宣言”,该宣言描述了我们如何设想线程成为该语言未来的关键部分,其链接可以在Julia 手册中找到关于具有每个字段原子的多线程

我们对此感到非常兴奋。我们已经看到生态系统中的一些包基于这个基础来提供线程安全的抽象:

  • JuliaConcurrent/ConcurrentCollections.jl:共享状态的队列和字典。
  • JuliaActors/Actors.jl:使并发易于理解和推理的模式。
  • tkf/ThreadsX.jl:一些基本函数的并行版本。
  • JuliaFolds/Transducers.jl:基于线程 (foldxt) 和基于进程 (foldxd) 的并行性,具有相同的可组合 API。
  • JuliaFolds/FLoops.jl:在复杂集合上生成快速的通用顺序和并行迭代。

包管理器
自动安装包

如果某个包存在于注册表中但未安装,则现在可以在 REPL 中尝试加载包时会提供自动安装。

之前:

julia>  using Foo
ERROR: ArgumentError: Package Foo not found in current path:
- Run `import Pkg; Pkg.add("Foo")` to install the Foo package.

Stacktrace:
 [1] require(into::Module, mod::Symbol)
   @ Base ./loading.jl:871

(@1.6) pkg> add Foo
...

julia>  using Foo

julia>  Foo
Foo

现在:

julia>  using Foo
 │ Package Foo not found, but a package named Foo is available from a registry.
 │ Install package?
 │   (@v1.7) pkg> add Foo
 └ (y/n) [y]: y
 ...
julia>  Foo
Foo

默认情况下,该软件包将安装到当前活动环境中,通过y或 单个return按键选择。要取消选择n或使用Ctrl-c。

New manifest format

每当用户在 Julia 中添加包时,包管理器 (Pkg) 都会写出一个名为“manifest”的 TOML 文件,其中包含该包所有依赖项的确切版本。不同的包版本可能与不同的 Julia 版本兼容,因此“resolver”(为项目中的所有包和依赖项计算一组兼容版本的算法)的输出因此依赖于 Julia 版本。因此,不建议将在一个 Julia 版本中创建的manifest与另一个 Julia 版本一起使用。如果 Pkg 可以在发生这种情况时警告您,那将会很方便。

为了发出这样的警告,Pkg 需要知道哪个 Julia 版本生成了给定的manifest。但是,manifest的当前format(或架构)使得添加此类信息变得困难。这样做的原因是format使得 TOML 文件中的顶级键是依赖项的包名称。这意味着没有任何空间可以添加诸如julia_version条目之类的内容。当然,可以对具有此名称的条目进行特殊处理(假设没有人会准确命名包julia_version),但是如果没有相同的“结构”条目指代两个完全不同的事物会更好。

1.7 版中所做的是更改此manifestformat,以便所有依赖项都放在一个公共[deps]密钥下。这释放了全局命名空间,以便julia_version可以添加条目。它还开辟了向manifest添加未来有用数据的可能性。读取此类manifest的能力也将向后移植到 Julia 1.6,因此在 Julia 1.6.2 及更高版本中。Pkg 还将保留现有manifest format,因此只有新manifest才会采用新的manifest format。

改进 Windows 和分布式文件系统上注册表的性能

我们注意到一些关于 Julia 包管理器 (Pkg) 在 Windows 和网络文件系统 (NFS) 上速度的抱怨。这些之间的共同点是这些系统的文件操作往往要贵得多。在 Julia 1.7 中,我们花了一些时间来识别和改进这种情况。

General registry 是 Pkg 用于查找有关包的信息的默认注册表。它的结构使得每个包都有四个不同的 TOML 文件。在撰写本文时,General 包含 5761 个包,这意味着它包含大约 23 000 个文件。Pkg 有两种获取注册表更新的方法,一种是通过 git 协议,另一种是通过 HTTPS 使用“Pkg Server”,这是一种社区驱动的托管软件包和注册表的方式,其中注册表作为下载压缩的 tarball。有报道称,在 Windows 上,一般注册表的初始下载需要几分钟的时间,而在 Linux 和 macOS 上,通常需要几秒钟。速度减慢的主要原因被诊断为 Windows Defender 在关闭文件时导致速度减慢,这在提取 23 000 个小文件时非常困难。Rust 社区在解压缩文档时面临类似的问题,并通过使用线程池仅用于关闭文件可以显着提高性能。

我们决定采取不同的路线,而不是使用线程池来加快关闭文件的速度。Julia 与p7zip捆绑在一起,与标准库一起,Tar.jl可以直接将压缩的 tarball 读入内存,而根本不需要具体化任何文件。这样做可以消除实现文件的问题,从而显着提高 Windows、NFS 和其他分布式文件系统(如 HPC 系统中通常使用的那些)上注册表的性能。

例如,我们可以看到从头开始安装 Example 包时对“clean”系统的影响。首先,使用解压缩所有文件的旧方法(约 30 秒):

julia>   @time Pkg.add("Example")
  Installing known registries into `C:\Users\Kristoffer Carlsson.julia`
   Resolving package versions...
   Installed Example ─ v0.5.3
 29.509835 seconds (4.81 M allocations: 320.162 MiB, 0.81% gc time)

然后使用将压缩的注册表直接读入内存的新方法(~2 秒):

julia>   @time Pkg.add("Example")
  Installing known registries into `C:\Users\Kristoffer Carlsson.julia`
   Resolving package versions...
   Installed Example ─ v0.5.3
  1.953665 seconds (2.35 M allocations: 164.310 MiB, 1.96% gc time)

Property Destructuring

新版本不仅支持通过迭代来解构对象,同时支持通过属性名称。(; a b)是根据 1.5 中添加的语法建模的,用于构造NamedTuple字段名称对应于使用的变量名称。

如何使用此语法的简单示例:

julia>  nt = (a=1, b=2)
(a = 1, b = 2)

julia>  (; a, b) = nt
(a = 1, b = 2)

julia>  a
1

julia>  b
2

(; a, b) = nt简单地等同于a = nt.a; b = nt.b,因此它不仅可以用于NamedTuples,还可以用于解构任何对象的属性,例如DataFrame也可以。一个myreal只提取复数实部的函数现在可以写成如下:

julia>  myreal((; re)::Complex) = re
myreal (generic function with 1 method)

julia>  myreal(2 + 3im)
2

此语法也与类型注释兼容(请注意,尽管在函数参数内部使用时,这些在调度中不起作用):

julia>  let
           (; a::UInt, b::Float64) = (a=1, b=2)
           b = 5
           a, b
       end(0x0000000000000001, 5.0)

支持苹果芯片

Julia v1.7 也是第一个在 Apple Silicon 上运行的版本,例如 M1 系列的 ARM CPU。这一功能的规划实际上从一年多前就开始了,当时 Apple 刚刚宣布新芯片。由于缺乏用于新平台的 Fortran 编译器,实现这一目标就很艰难,而这是构建 Julia 二进制依赖项之一,即 OpenBLAS 所必需的。当然,Julia并不是唯一受此问题影响的开源项目,最终通过 Iain Sandoe 开发的 GCC 分支可用性解决了这个问题。

虽然我们现在能够为这个平台提供预构建的 Julia 二进制文件,但目前它还是实验性项目,预计会出现特定的错误。得益于 Rosetta 2 兼容层,Julia 的 x86-64 (Intel) 二进制文件也可以在这些机器上运行,但性能会有所降低。

更多相关技术内容咨询欢迎前往并持续关注六星社区了解详情。 

如果你想用Python开辟副业赚钱,但不熟悉爬虫与反爬虫技术,没有接单途径,也缺乏兼职经验
关注下方微信公众号:Python编程学习圈,获取价值999元全套Python入门到进阶的学习资料以及教程,还有Python技术交流群一起交流学习哦。

attachments-2022-06-f7krWpj362b1771b18aea.jpeg

  • 发表于 2021-12-08 09:12
  • 阅读 ( 692 )
  • 分类:行业资讯

你可能感兴趣的文章

相关问题

0 条评论

请先 登录 后评论
轩辕小不懂
轩辕小不懂

2403 篇文章

作家榜 »

  1. 轩辕小不懂 2403 文章
  2. 小柒 1742 文章
  3. Pack 1135 文章
  4. Nen 576 文章
  5. 王昭君 209 文章
  6. 文双 71 文章
  7. 小威 64 文章
  8. Cara 36 文章