我有一个 Julia 模块,我需要从我的 python 代码库进行交互。为此,我像这样使用 pyjulia
。
import julia
j = julia.Julia()
j.include('./simulation/n-dof/dynamics.jl')
j.using("Dynamics")
print(j.sim([1,2,3],[1,2,3]))
但是,这会减慢一切,因为 Julia 需要编译我正在使用的模块。
我使用的模块导出 1 个函数并在内部使用 ForwardDiff
进行一些计算。它计算动态系统的导数。在可预见的 future ,该模块很可能不会改变。我一直在阅读有关 __precompile()__
和 PackageCompiler.jl
的内容,但我不太了解内部工作原理以及如何使用它。
那么有没有办法在 Julia 系统镜像中缓存模块(据我所知,这就是为什么干净的 Julia 启动速度很快)?还是将其编译为二进制文件然后以某种方式通过 python 调用它更好?我需要能够将参数传递给导出的函数。
我用于测试的动态模块示例:
module Dynamics
function sim(a,b)
return 1
end
export sim
end
最佳答案
这是一个复杂的问题。我会给出最简单的方法。我假设你使用 Julia 0.7(它应该很快发布):
一个。在 Julia 中生成一个包;在 Julia REPL 和 Pkg 管理器 session 中切换到包管理器(您使用 ]
切换到它)写入:generate Ex1
(Ex1
将是我们的包)
B.您将创建一个包骨架;添加您需要的任何依赖项。我假设你的简单例子。然后将src
目录下的文件Ex1.jl
修改为:
__precompile__()
module Ex1
export sim
sim(a,b) = 1
precompile(sim, (Int, Int))
end
C.关键行是 precompile(sim, (Int, Int))
因为你强制预编译 sim
函数 - 你必须指定你想要函数的参数类型预编译
D.将Julia目录更改为Ex1
包目录,在Pkg管理器模式下写入activate .
激活包
E.在 Pkg 管理器模式下编写 precompile
;这将触发模块的预编译。您可以在 compiled/v0.7/
子目录中的 DEPOT_PATH[1]
目录中检查创建了 Ex1
目录,它包含 ji
包含预编译包内容的文件
如何检查包是否真的预编译了?退出 Julia 并再次进入 Ex1
包的目录(以获得干净的 REPL)。现在写:
一个。 在 Pkg 管理器模式下激活 .
(使 Ex1
可见)
B.返回正常的 Julia 模式并运行以下命令:
julia> using Ex1
julia> @time sim(1,1)
0.000003 seconds (5 allocations: 208 bytes)
1
julia> @time sim(1,1)
0.000003 seconds (4 allocations: 160 bytes)
1
julia> @time sim(1.0,1.0)
0.000182 seconds (394 allocations: 26.641 KiB)
1
julia> @time sim(1.0,1.0)
0.000002 seconds (4 allocations: 160 bytes)
1
您可以看到 sim(1,1)
没有编译,因为我们已经为 (Int,Int)
参数预编译了 sim
,但是 sim(1.0,1.0)
必须编译,因为我们没有为 (Float64,Float64)
预编译 sim
。
总而言之:要理解的关键是您预编译的不是函数,而是该函数的特定方法。您将必须预编译您将以这种方式使用的所有方法。上面解释中的所有其余部分都是让 Julia 进行预编译的技术步骤。
要记住的其他问题:
- 你可以把包构建到系统镜像中,这很复杂;这里有说明:https://docs.julialang.org/en/latest/devdocs/sysimg/ ;您还可以查看您提到的 PackageCompiler.jl 以帮助您完成此过程;可以预见静态预编译在未来会变得更好;
- 为了使您的包可预编译,所有依赖项都必须是可预编译的。
希望以上内容对您有用。
关于python - 缓存 Julia 模块以在 Python 中更快地启动和使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51456464/