Julia 的构建方式使您永远看不到完整的类似 PETSc 的库,这是故意的。PETSc 不是一个单一的东西:它是一个 HPC 库,具有一些实用函数、线性求解器、非线性求解器……一整罐在它自己的世界内工作但不在其外的汤。
Julia 的包生态系统建立在泛型和可组合性之上。对于这种情况,最好用一个例子来解释它。CUDA.jl为基于 CUDA 的数组操作提供CuArray
类型。如果您x .+ y .* z
使用 CuArray,它会使用 .ptx JIT 编译器按(x,y,z) -> x + y * z
元素生成函数并通过 CUDA 应用映射。它具有高级操作,因此A*x
在 GPU 上,并且A\x
在 GPU 上。
但是与 PETSc 相比,CUDA.jl 是不完整的吗?像 GMRES 这样的迭代求解器在哪里?好吧,如果有人为也使用泛型的迭代求解器编写 Julia 库,那么它就是 CUDA.jl 的“最”迭代求解器。例如Krylov.jl有这样的 CG/GMRES/等。实施。对于 ODE 求解器,DifferentialEquations.jl。非线性求解器NonlinearSolve.jl等等。泛型都足够好,如果你使用 GPU 数组,包中的所有计算都重新编译到 GPU 上,如果它是分布式的,它不会在没有你要求的情况下进行内存传输等。
所以这将问题改变为以下问题:什么是好的数组类型以及它们可以与什么一起使用?SciML生态系统通常与通用数组类型兼容,因此您可以在那里找到额外的功能(由于劳动力更大、关注点分离等原因,它比 PETSc 做得更多)。所以真正的过剩是数组类型。有很多好的,但对于分布式来说,它不太完整。这是一般摘要:
- CUDA.jl - 基于 CUDA 的数组。非常好,非常完整,使用 codegen 可以轻松生成新内核,因此它支持大多数操作。以多种方式与多 GPU 配合使用。仅限英伟达 GPU。
- ROCArrays.jl - 类似于 CUDA.jl,但基于 ROC 的支持(AMD GPU)。不如 CUDA.jl 完整,往往会遗漏更多的线性代数,但相当可用。
- ArrayFire.jl - 基于 ArrayFire 的“通用 GPU”。与其他两个相比,它会损失性能,因为它不包括用于融合 GPU 调用的内核生成,但它仍然是一个不错的选择。比其他两个用得少得多。
- DistributedArrays.jl - 用于分布式 HPC 的东西,但它很慢并且缺少很多线性代数。对于大多数线性代数运算,它将依赖 Elemental.jl。
- MPIArrays.jl - 基于 MPI 的数组类型的一个很好的原型,遗憾的是它不再维护太多。
- PETSc.jl - 正在处理一个包装器,主要是为了让数组类型
Mat
足够完整,以完成我提到的通用包用法。
如您所见,分布式数组类型需要做更多的工作,但这正是您要寻找的。不一定是类似 PETSc 的东西,而只是提供了一个可靠的分布式阵列以与下游功能一起使用。