gpt4 book ai didi

julia - 处理 Julia 中 kwargs 的类型

转载 作者:行者123 更新时间:2023-12-03 05:43:57 26 4
gpt4 key购买 nike

如何在 Julia 函数中使用 kwargs 并声明其类型以提高速度?

function f(x::Float64; kwargs...)
kwargs = Dict(kwargs)
if haskey(kwargs, :c)
c::Float64 = kwargs[:c]
else
c::Float64 = 1.0
end
return x^2 + c
end

f(0.0, c=10.0)

产量:

ERROR: LoadError: syntax: multiple type declarations for "c"

当然,我可以将函数定义为 f(x::Float64, c::Float64=1.0) 来实现结果,但是我有许多带有默认值的可选参数要传递,所以我更喜欢使用 kwargs。

谢谢。

Related post

最佳答案

正如另一个答案中所指出的,只有当您遇到类型不稳定时,这才真正重要。如果你这样做,答案就是对你的功能进行分层。有一个进行类型检查和各种设置的顶层,然后调用一个使用分派(dispatch)的函数来加快速度。例如,

function f(x::Float64; kwargs...)
kwargs = Dict(kwargs)
if haskey(kwargs, :c)
c = kwargs[:c]
else
c = 1.0
end

return _f(x,c)
end
_f(x,c) = x^2 + c

如果你的大部分时间都花在内部函数上,那么这会更快(对于非常简单的函数可能不是这样)。这也允许非常一般的用法,其中您有一个关键字参数默认 nothing 和 do 和 if Nothing ... ,这可以设置一个复杂的默认值,而不是必须担心类型稳定性,因为它将受到内部函数的屏蔽。

这种对性能敏感的内部函数之上的高级类型检查包装器在 DifferentialEquations.jl 中被大量使用。查看高级包装器 for the SDE solvers通过确保类型稳定性(内部函数是 sde_solve)带来了很好的加速(或者查看 ODEProblemsolve,它要复杂得多因为它处理不同包的转换,但它是相同的想法)。

对于像你这样的小例子,在this PR merges之后可能会有一个更简单的答案。 .

<小时/>

为了解决一些困惑,这里有一个声明表:

function f(x::Float64; kwargs...)
local c::Float64 # Ensures the type of `c` will be `Float64`
kwargs = Dict(kwargs)
if haskey(kwargs, :c)
c = float(kwargs[:c])
else
c = 1.0
end

return x^2 + c
end

这将强制任何保存到 c 的内容转换为 Float64 或错误,从而实现类型稳定性,但不是通用的解决方案。您使用什么形式实际上取决于您在做什么。

最后,还有类型断言,如 @TotalVerb 所示:

function f(x::Float64; c::Float64=1.0, kwargs...)
return x^2 + c
end

这很干净,或者您可以在函数中断言:

  function f(x::Float64; kwargs...)
kwargs = Dict(kwargs)
if haskey(kwargs, :c)
c = float(kwargs[:c])::Float64
else
c = 1.0
end

return x^2 + c
end

这只会在发生断言的行上引起转换(即@TotalVerb形式不会调度,所以你不能用c::Int创建另一个函数,它会仅在首次读入关键字 arg 时断言(转换))。

<小时/>

摘要

  1. 无论用户使用什么类型 c,第一个解决方案都会调度为 _f 类型稳定,因此如果 _f > 是一个很长的计算,这将获得几乎最佳的性能,但对于真正快速的调用,它将产生调度开销。

  2. 第二个解决方案将通过强制将 c 设置为 Float64 来修复任何类型稳定性(它将尝试转换,如果可以的话) t,错误)。因此,这可以通过强制类型稳定性或错误来提高速度。

  3. 关键字点中的断言(@TotalVerb 的答案)是最干净的,但稍后不会自动转换(因此您可能会得到类型不稳定。但如果您稍后不小心转换它,那么你就具有类型稳定性,可以推断类型,因此你将获得最佳性能)并且你不能将其扩展到函数将 c 作为其他类型传入的情况(无调度) .

  4. 最后一个解决方案与 3 几乎相同,只是没有那么好。我不会推荐它。如果您正在使用断言做一些复杂的事情,那么您可能设计了错误,或者确实想做第一个类似的事情(在类型稳定的较长函数调用中分派(dispatch))。

但请注意 dispatch with version 3 may be fixed in the near future ,这将允许您使用 c::Float64c::Int (如果需要)使用不同的函数。希望您的解决方案就在这里。

关于julia - 处理 Julia 中 kwargs 的类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39601800/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com