julia - 闭包列表的类型稳定性

标签 julia type-stability

我正在尝试在 Julia 中设计一些代码,这些代码将采用用户提供的函数列表,并基本上对它们应用一些代数运算。

看来如果这个函数列表是闭包,则不会推断它们的返回值,导致根据@code_warntype 导致代码类型不稳定。

我尝试为闭包提供返回类型,但似乎无法找到正确的语法。

下面是一个例子:

functions = Function[x -> x]

function f(u)
    ret = zeros(eltype(u), length(u))

    for func in functions
        ret .+= func(u)
    end

    ret
end

运行这个:
u0 = [1.0, 2.0, 3.0]
@code_warntype f(u0)

并获得
Body::Array{Float64,1}
1 ─ %1  = (Base.arraylen)(u)::Int64
│   %2  = $(Expr(:foreigncall, :(:jl_alloc_array_1d), Array{Float64,1}, svec(Any, Int64), :(:ccall), 2, Array{Float64,1}, :(%1), :(%1)))::Array{Float64,1}
│   %3  = invoke Base.fill!(%2::Array{Float64,1}, 0.0::Float64)::Array{Float64,1}
│   %4  = Main.functions::Any
│   %5  = (Base.iterate)(%4)::Any
│   %6  = (%5 === nothing)::Bool
│   %7  = (Base.not_int)(%6)::Bool
└──       goto #4 if not %7
2 ┄ %9  = φ (#1 => %5, #3 => %15)::Any
│   %10 = (Core.getfield)(%9, 1)::Any
│   %11 = (Core.getfield)(%9, 2)::Any
│   %12 = (%10)(u)::Any
│   %13 = (Base.broadcasted)(Main.:+, %3, %12)::Any
│         (Base.materialize!)(%3, %13)
│   %15 = (Base.iterate)(%4, %11)::Any
│   %16 = (%15 === nothing)::Bool
│   %17 = (Base.not_int)(%16)::Bool
└──       goto #4 if not %17
3 ─       goto #2
4 ┄       return %3

那么,如何使这种代码类型稳定?

最佳答案

如果您想要任意函数的类型稳定性,则必须将它们作为元组传递,这允许 julia 提前知道将在哪个阶段应用哪个函数。

function fsequential(u, fs::Fs) where Fs<:Tuple
    ret = similar(u)
    fill!(ret, 0)
    return fsequential!(ret, u, fs...)
end

@inline function fsequential!(ret, u, f::F, fs...) where F
    ret .+= f(u)
    return fsequential!(ret, u, fs...)
end
fsequential!(ret, u) = ret

julia> u0 = [1.0, 2.0, 3.0]
3-element Array{Float64,1}:
 1.0
 2.0
 3.0

julia> fsequential(u0, (identity, x-> x .+ 1))
3-element Array{Float64,1}:
 3.0
 5.0
 7.0

如果你用 @code_warntype 检查这个你会看到它是可推断的。
fsequential!是有时被称为“lispy 元组编程”的一个示例,在该示例中,您一次迭代处理一个参数,直到用完所有可变参数。这是一个强大的范式,允许比 for 更灵活的推理。 -loop 与数组(因为它允许 Julia 为每个“循环迭代”编译单独的代码)。但是,它通常仅在容器中的元素数量相当少时才有用,否则最终会导致编译时间过长。

类型参数FFs看起来没有必要,但它们旨在强制 Julia 专门为您传入的特定函数编写代码。

关于julia - 闭包列表的类型稳定性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55840333/

相关文章:

string - Julia 中的单引号和双引号

julia - 函数中 julia 中的抽象类型数组

testing - Julia :我可以在没有 `makedocs` 的情况下运行 doctests 吗?

Julia GLM - 使用 devresid 进行绘图

julia - 爱因斯坦求和张量中的矩阵和 Julia 中的另一个张量

types - 使用浮点输入时,在 Julia 中键入稳定函数以进行一般分布

arrays - Julia 中的手动类型推断

julia - Julia 中类型稳定的 do-blocks