使用朱莉娅中的SymPy来转换表达式的字符串,我注意到本机Julia函数fast_fct的实现与由字符串生成的SymPy函数slow_fct之间的性能差异为3500。是否有一种方法可以加快SymPy函数的速度,还是有一种不同的、更快的方法来实现相同的功能?
请授予How to lambdify a list of strings with SymPy in Julia?函数string_to_function。
最小工作实例:
using SymPy
function string_to_function(fct_string)
expression = SymPy.sympify.(fct_string)
variables = free_symbols(expression)
function(args...)
subs.(expression, (variables .=> args)...)
end
end
function fast_fct(x, y, z)
return x + y + z
end
slow_fct = string_to_function("x + y + z")基准测试
N = 100000
@time for i in 0:N
x, y, z = rand(3)
fast_fct(x, y, z)
end
@time for i in 0:N
x, y, z = rand(3)
slow_fct(x, y, z)
end与近似结果
>>> 0.014453 seconds (398.98 k allocations: 16.769 MiB, 40.48% gc time)
>>> 31.364378 seconds (13.04 M allocations: 377.752 MiB, 0.64% gc time, 0.41% compilation time)发布于 2021-10-07 12:59:16
为此,在lambdify中有一些示例。安东内洛指出,Symbolics可能更快--他们有一个更好的lambdify版本--但是在这里使用@eval可能足够好:
julia> @btime fast_fct(x...) setup=(x=rand(3))
86.283 ns (4 allocations: 64 bytes)
2.2829680705749293
julia> med_fct = lambdify(SymPy.sympify("x + y + z"))
#101 (generic function with 1 method)
julia> @btime med_fct(x...) setup=(x=rand(3))
939.393 ns (16 allocations: 304 bytes)
1.5532948656814223
julia> ex = lambdify(SymPy.sympify("x + y + z"), invoke_latest=false)
:(function var"##321"(x, y, z)
x + y + z
end)
julia> @eval asfast_fct(x,y,z) = ($ex)(x,y,z) # avoid invoke_latest call
asfast_fct (generic function with 1 method)
julia> @btime asfast_fct(x...) setup=(x=rand(3))
89.872 ns (4 allocations: 64 bytes)
1.1222502647060117发布于 2021-10-06 15:25:56
实际上,通过适当的基准测试,差别甚至更大,因为你也在测量其他的东西.
using BenchmarkTools
x, y, z = rand(3)
@btime fast_fct($x, $y, $z) # 4.500 ns (0 allocations: 0 bytes)
@btime slow_fct($x, $y, $z) # 162.210 μs (119 allocations: 3.22 KiB)几点意见:
Symbolics.jl。这应该要快得多(但是,像这样的例子,它永远不会关闭.)。然而,这是非常新的,而且这个文档还没有好到可以理解的程度。https://stackoverflow.com/questions/69467593
复制相似问题