“Julia”科学计算语言项目有多成熟?

计算科学 并行计算 语言 朱莉娅
2021-11-23 19:31:13

我正在考虑学习一种用于数值/模拟建模项目的新语言,作为我目前使用的 C++ 和 Python 的(部分)替代品。我遇到了Julia,这听起来很完美。如果它完成了它声称的一切,我可以在我的所有项目中使用它来替换 C++Python,因为它可以访问高级科学计算库代码(包括 PyPlot)以及以与 C 相似的速度运行 for 循环。我还将受益于其他任何一种语言中都不存在的适当协程之类的东西。

然而,这是一个相对较新的项目,目前版本为 0.x,我发现各种警告(在过去的不同日期发布)它还没有为日常使用做好准备。因此,我想要一些关于项目状态的信息(2014 年 2 月,或任何时候发布答案),以帮助我评估我个人是否应该考虑在这个阶段投入时间来学习这门语言。

我将不胜感激有关 Julia 项目的具体相关事实的答案;我对基于其他项目经验的意见不太感兴趣。

特别是,Geoff Oxberry 的评论表明 Julia API 仍处于不断变化的状态,需要在代码更改时进行更新。我想了解这种情况的程度:API 的哪些区域是稳定的,哪些可能会改变?

我想通常我会主要做线性代数(例如解决特征问题),ODE 与许多变量的数值积分,使用 PyPlot 和/或 OpenGL 绘图,以及低级 C 风格的数字运算(例如,用于蒙特卡洛模拟)。Julia 的图书馆系统是否在这些领域得到了充分的发展?特别是,对于这些类型的活动,API 是否或多或少是稳定的,或者我是否会发现我的旧代码在升级到新版本的 Julia 后往往会崩溃?

最后,在决定目前是否将 Julia 用于严肃的工作时,是否还有其他值得考虑的问题?

4个回答

Julia,在这一点上(2019 年 5 月,Julia v1.1 和 v1.2 即将问世)对于科学计算来说已经相当成熟了。v1.0 的发布标志着每年代码破坏的结束有了这个,许多科学计算库都有时间在没有中断的情况下简单地增长。可以在pkg.julialang.org找到有关 Julia 包的广泛概述。

对于核心科学计算,DifferentialEquations.jl库用于微分方程(ODE、SDE、DAE、DDE、Gillespie 模拟等),Flux.jl用于神经网络,以及JuMP库用于数学规划(优化:线性、二次、混合整数等编程)是科学计算生态系统的三个基石。特别是微分方程库比您在其他语言中看到的要发达得多,有一个大型开发团队实现了诸如EPIRK 积分器龙格-库塔-尼斯特罗姆、刚性/微分-代数延迟微分方程自适应时间刚性随机微分方程积分器,以及一系列其他好东西,如伴随灵敏度分析化学反应 DSL、无矩阵 Newton-Krylov 和完全(无数据传输)GPU 兼容性,以及神经微分方程的训练,所有这些都具有出色的基准测试结果(免责声明:我是首席开发人员)。

成熟的 Julia 生态系统有点令人难以置信的是它的可组合性。从本质上讲,当有人构建像DifferentialEquations.jl 中那样的通用库函数时,您可以使用任何AbstractArray/Number 类型即时生成新代码。例如,有一个用于错误传播的库 ( Measurements.jl ),当您将其粘贴到 ODE 求解器中时,它会自动编译新版本的 ODE 求解器,该版本在没有参数采样的情况下进行错误传播正因为如此,您可能没有发现某些功能的文档,因为这些功能的代码会自行生成,因此您需要更多地考虑库的组合。

组合最有用的方法之一是线性代数。例如,ODE 求解器允许您指定jac_prototype,让您为其指定将在内部使用的雅可比行列式的类型。当然,LineraAlgebra 标准库中有类似的东西SymmetricTridiagonal你可以在这里使用,但考虑到类型泛型算法中可组合性的实用性,人们现在已经构建了整个数组类型库。BandedMatrices.jlBlockBandedMatrices.jl是定义(块)具有快速lu重载的带状矩阵类型的库,使它们成为加速偏微分方程系统的刚性 MOL 离散化求解的好方法。PDMats.jl允许指定正定矩阵。Elemental.jl允许您定义分布式稀疏雅可比行列式。CuArrays.jl在 GPU 上定义数组。等等。

然后你就有了所有的号码类型。Unitful.jl在编译时进行单元检查,因此它是一个无开销的单元库。DoubleFloats.jl与Quadmath.jlArbFloats.jl一起是一个快速的高精度库ForwardDiff.jl是一个用于正向模式自动微分的库,它使用双数运算。我可以继续列出这些。是的,您可以将它们放入足够通用的 Julia 库中,例如 DifferentialEquations.jl,以编译专门针对这些数字类型优化的版本。甚至像ApproxFun.jl这样的东西这是作为代数对象的函数(如 Chebfun)与这个通用系统一起使用,允许将 PDE 指定为函数空间中标量上的 ODE。

鉴于可组合性的优势以及可以使用类型在通用 Julia 函数上生成新的高效代码的方式,已经有很多工作将核心科学计算功能的实现引入纯 Julia。Optim.jl用于非线性优化,NLsolve.jl用于求解非线性系统,IterativeSolvers.jl用于线性系统和特征系统的迭代求解器,BlackBoxOptim.jl用于黑盒优化等。甚至神经网络库Flux.jl也只使用 CuArrays。 jl 将代码自动编译到 GPU 以实现其 GPU 功能。这种可组合性是在 DiffEqFlux.jl 中创建诸如神经微分方程之类的东西的核心. 像Turing.jl这样的概率编程语言现在也相当成熟,并且使用相同的底层工具。

由于 Julia 的库基本上是基于代码生成工具的,因此围绕代码生成有很多工具也就不足为奇了。Julia 的广播系统动态生成融合内核,这些内核被数组类型重载,以提供上述许多功能。CUDAnative.jl允许将 Julia 代码编译为 GPU 内核。ModelingToolkit.jl自动将 AST 脱糖成用于转换数学代码的符号系统。卡带.jl让您“叠加”其他人的现有功能,使用规则在编译前更改他们的功能(例如:将他们的所有数组分配更改为静态数组分配并将操作移至 GPU)。这是更高级的工具(我不希望从事科学计算的每个人都能直接控制编译器),但这就是许多下一代工具的构建方式(或者更确切地说,功能是如何编写自己的)。

至于并行性,我提到过 GPU,而 Julia内置了多线程和分布式计算Julia 的多线程将很快使用并行任务运行时 (PARTR) 架构,该架构允许嵌套多线程的自动调度如果你想使用 MPI,你可以使用MPI.jl当然,最简单的利用它的方法就是使用 AbstractArray 类型设置来在其操作中使用并行性。

Julia 还拥有您所期望的用于科学应用的通用语言的基本底层生态系统。它具有带有内置调试器的Juno IDE,它具有用于制作各种绘图的Plots.jl 。许多特定的工具也很好,比如Revise.jl 会在文件保存时自动更新你的函数/库。你有你的DataFrames.jlstatistics libraries等。最好的库之一实际上是Distributions.jl,它允许你编写分布通用的算法(例如:rand(dist)接受传入的任何分布的随机数),并且有大量的单变量和多变量分布(当然调度发生在编译时,这使得这一切都像硬编码特定于分布的函数一样快)。有一堆数据处理工具Web 服务器等,你可以命名它。在这一点上,它已经足够成熟,如果有一个基本的科学事物并且你期望它存在,你只需用 .jl 或 Julia 谷歌它就会出现。

然后有一些事情要记住在地平线上。PackageCompiler正在寻求从 Julia 库构建二进制文件,它已经取得了一些成功,但需要更多的开发。Makie.jl是一个完整的具有交互性的 GPU 加速绘图库,它仍然需要做更多的工作,但它确实希望成为 Julia 中的主要绘图库。Zygote.jl是一个源到源自动区分库,它不存在基于跟踪的 AD(Flux 的 Tracker、PyTorch、Jax)的性能问题,并且希望适用于所有纯 Julia 代码。等等。

总而言之,你可以在很多地方找到很多动静,但在大多数地区已经有了一个坚实成熟的库。它不再是你问“它会被采用吗?”的地方:Julia 已被足够多的人采用(数百万次下载),它有动力永远留在身边。它有一个非常好的社区,所以如果你只是想轻而易举地谈论并行计算或数值微分方程,一些最好的聊天室在Julialang Slack中。它是否是你应该学习的语言是一个个人问题,它是否适合你的项目是一个技术问题,它们是不同的。但它是一种已经成熟并得到大量一致开发人员支持的语言吗?这似乎是肯定的。

如果没有,是否有可能给出一个粗略的数量级估计,在再次考虑之前我应该​​等待多长时间?

我对计算科学语言成熟需要多长时间的粗略估计大约是十年。

示例 1:SciPy 始于 2001 年左右。2009 年,Scipy 0.7.0 发布,ODE 集成器有一个与 VODE 的接口(ode15s大致相当于 ;ode15s是基于 NDF 的,VODE 是 BDF/Adams-Bashforth,具体取决于)。使用 SciPy 0.10.0 的接口dopri5,大致相当于 MATLAB 的接口,这是ode45一种 Runge-Kutta 4 阶方法,通常作为第一个实用的数值积分方法引入本科生。SciPy 0.10.0 于 2011 年 12 月发布,他们花了大约 10 年的时间才将 MATLAB 的一项功能引入我认识的每个工程本科生。

示例 2:Mathworks 成立于 1984 年。在他们的第一个版本中,他们使用了一个名为 JACKPAC 的 LAPACK 端口到 C(以编写它的 MathWorks 工程师 Jack Little 的名字命名)。他们直到 2000 年才用 LAPACK 取代它。

Julia 可能需要更少的时间,但我估计从成立到成为主流大约需要 10 年。(它已经发布了一年左右;那么可能是 9-10 年?)

Julia 的图书馆系统是否在这些领域得到了充分的发展?特别是,对于这些类型的活动,API 是否或多或少是稳定的,或者我是否会发现我的旧代码在升级到新版本的 Julia 后往往会崩溃?

我不使用 Julia,所以请对我说的话持保留态度,因为我只看到 Jeff Bezanson 就 Julia 做过演讲。他们竭尽全力使链接和使用来自 C、Python 和 Fortran 的库变得容易。如果您找不到可以满足您需求的 Julia 库,请使用更成熟的语言为库编写 Julia shim。因此,我不认为缺少库是一个问题。我认为一个问题是确保对核心语言功能的更改不会让您感到厌烦。如果您查看 Julia Git 存储库中的里程碑,您会发现“破坏”标签的使用频率很高(在 0.2 版本中使用了 12 次,在 0.3 版本中使用了 5 次)。对我来说,这表明核心语言仍在发展,这就是我现在犹豫使用该语言的原因。

编辑:Aurelius 提出了一个很好的观点:

是什么让你认为 Julia 会真正成为主流,而不是像许多其他语言一样默默无闻地消亡?SciPy/numpy 拥有/拥有不断增长的 python 社区的支持,而 Julia 没有。

在最初的答案中,我决定避开“朱莉娅会成功成为主流吗?”的问题。越多越好。失败很容易;成功是困难的。我认为 Julia 最好的比较是与 MATLAB、R 和 Octave 等技术计算语言。HPC 语言(Chapel、Fortress、UPC 等)的受众比技术计算语言更窄,而通用语言(C、Python、C++ 等)的受众比技术计算语言更广泛。

我认为有助于 Julia 的东西是在不牺牲表现力的情况下为性能而设计。与 MATLAB、R 甚至 Python 相比,Julia 与 C 等编译语言相比更具竞争力。这个设计目标也是一个可以从现有语言中吸引人们的功能,例如:

  • 非常关心性能并且来自 C 和 Fortran 等语言,但愿意牺牲一点性能(可能是2ish的一个因素)来从编译语言转向更少行的解释语言(以及用于更快速的开发和测试)。
  • 关心高生产力并来自 Python、R 和 MATLAB 等语言但想要更高性能的人。在执行方面,纯 Python、纯 MATLAB 和纯 R 都很慢。这些语言的开发人员已经竭尽全力将库包装在编译语言中,但是您无法包装所有内容,并且在某些时候,核心语言会减慢您的速度。Core Julia 速度更快,可以让您更快地完成更多科学工作。
  • 关心自由软件的人。Julia 是解释型和自由的(Python、Octave 等也是);MATLAB 不是。

Julia 也在尝试促进并行性。我觉得没有足够的资格扩展这一点,我不认为这是该语言的主要吸引力,但我认为这是他们正在努力的一个卖点,我希望其他人能够阐明这一点。

然而,即使他们有技术优势,语言创造者也必须做一些跑腿工作来推广语言和传福音。Jeff Bezanson、Alan Edelman、Stephen Karpinski 和 Viral Shah 正在努力使该语言取得成功。Alan Edelman 与计算科学界有着深厚的联系,他之前曾参与过语言级项目(尤其是 MATLAB 的 Star-P 扩展)。一段时间以来,Jeff Bezanson 一直在做巡回会议,将 Julia 提升为计算科学家和工程师。在麻省理工学院,他们在招募学生和教职员工(尤其是 Steven G. Johnson)方面做得很好,他们通过向 Julia 添加库来做出贡献。他们在《连线》杂志上发表了一篇文章,并设法为自己找到了一篇维基百科的文章,这一切都在仅仅一年之后。他们的 Git 仓库有数千颗星,数百个分叉,和数百只手表,因此按照开源标准,他们的项目取得了成功。我认为到目前为止,他们已经做了所有正确的事情,所以这是维持这种努力和建立社区的问题。他们仍然可能失败,但走到这一步向我表明他们有合理的成功机会。

我相信 Julia 值得学习。我已经用它生成了一些研究有限元代码,并且非常快速地生成它们。我对我的经历感到非常满意。

Julia 为我启用了一个我发现很难用其他语言实现的工作流程。您可以将其用作 MATLAB 之类的原型设计语言,但与 MATLAB 不同的是,当您拥有工作代码并通过分析迭代来加速它时,用 C 代码替换热点是轻松的。他们将与 C(和 Python)的接口作为设计的优先事项。

因此,该语言使我能够非常迅速地从我的数学公式转移到函数代码,然后从函数代码转移到高性能代码。我认为 Julia 的这个功能被低估了,但它增加了巨大的价值。

在许多情况下,我在生成功能有限元代码后的几个小时内就获得了 C 性能(与我自己的 C 代码相比)。到目前为止,如果我只使用 Julia 功能,我通常会比 C 慢约 3 倍。在此之后,我用 C 函数替换热点(Julia 带有一个堆栈采样分析器来帮助识别这些)。通常这只需要用“ccall”替换有问题的热点代码行,而 Julia 会处理任何编组。

我认为 Julia 现在缺少的主要东西让我犹豫是否考虑将它用于更大的项目是缺乏完全支持的调试器,并且对绘图的支持很差(现在你最好的绘图选择实际上只是 matplotlib 的一个接口我经常休息)。对代码的即时反馈非常重要。没有交互式调试我也不知道如何生存,在这方面我被 MATLAB 和 GDB 宠坏了。

根据我的经验,Julia 还没有为(科学的)日常使用做好准备(我说的是 2016 年 3 月的稳定版 0.4)。语言本身很好,功能丰富且一致;从 matlab 和 python 向前迈出了令人耳目一新的一步。当然,即使在这个早期阶段,Julia 也是一个不错的选择。但是,如果您需要可靠且成熟的科学图书馆,我不建议您现在采取行动。我遇到的主要问题是:

  • Julia 核心之外的软件包不可靠。它们因更新、更改、被替换而中断,有时不完整或只是损坏。
  • Julia 的并行特性(imo 最有前途的潜在 matlab 杀手特性)还不成熟。您将遇到分段错误、内存泄漏、崩溃和令人失望的性能。有时它们不能很好地与 julia 的其他部分配合使用,例如一些线性系统的求解器或内核之外的包。虽然这些功能听起来很有希望,但对我来说,它们经常失败。@parallel仅仅在 for 循环前面写几乎是不够的,理论上它应该写在哪里。
  • 许多小事情、小错误和一个可以忍受的问题:不太好,有时是错误的调用堆栈跟踪,有一点错误的解释器历史记录,包加载缓慢,一个或另一个包/函数的性能不佳等等。让我恼火的是大多数是 PyPlot 包,它是 matplotlib 的包装器,目前没有替代品。它在那里真的很棒,而且它大部分都有效。但是,如果您需要绘制数据,请为性能非常缓慢和问题做好准备。

这一切都会好起来的。我相信有一天 Julia 会在几乎所有方面都优于 matlab 和 python。很有可能会为它开发创新的软件包。似乎已经有一个大社区。即使是现在,也有大量的包包含从 opencl 到 webservers 的用例。使用 python 或 c 库非常容易,因此在库可用性方面您可能不会碰壁。Julia 的一大优势在于可以毫不费力地将来自各种来源的高性能功能以现代且一致的高级语言粘合在一起(参见上面的答案)。但总的来说,我发现它既不够成熟也不够稳定,无法有效使用。