julia 闭包中的数组分配

Array allocation in julia closure

我想知道在 let-block 中分配临时数组是不是个好主意,它包装了一些函数? 一些玩具示例:而不是

function foo(x)
    y = zeros(100)
    for i in 1 : 100
        y[i] = 2*x[i] - 1
    end
    do_something(y)
end

我会这样写:

let
  const y = zeros(100) # otherwise foo will be type-unstable due to 'global' y
  function foo(x)
    for i in 1 : 100
        y[i] = 2*x[i] - 1
    end
    do_something(y)
  end
end

可以通过@benchmark 宏轻松检查,在第二种情况下,y 数组的内存将只分配一次,这显着提高了性能(在我的非玩具案例中)。我想知道做这样的事情是 "julian-way" 吗?

我给你Julia 1.0的答案。对于早期版本的 Julia,情况会有所不同。

要点 1。在 Julia 1.0 下,您使用 let 的代码将不会 运行,因为 let 创建本地范围,并且在本地范围内您不能使用 const .

第 2 点。在全局范围内做这样的事情是完全可以的:

const y = zeros(100) # otherwise foo will be type-unstable due to 'global' y
function foo(x)
    for i in 1 : 100
        y[i] = 2*x[i] - 1
    end
    do_something(y)
end

你会有很好的性能,因为 Julia 1.0 知道 y 有常量类型并且会优化它。结果是您将在全局范围内拥有 y,在方法 table 中拥有 foo(即您可以使用其名称调用 foo)。

第 3 点。您也可以像这样使用 let 块:

const foo = let y = zeros(100)
    function inner_foo(x)
        for i in 1 : 100
            y[i] = 2*x[i] - 1
        end
        do_something(y)
    end
end

这次 y 仅在本地范围内定义,不会泄漏到全局范围。此外 inner_foo 未在全局范围内定义,因此您必须将 let 块的 return 值分配给变量 foo 然后可用于进行调用(我将其设为 const 以提高性能(如果稍后在某些函数中使用它)

第 4 点。但是请注意,这段几乎相同的代码不会那么好,因为 Julia 1.0 在变量类型推断方面存在问题 y(希望将来会修复)

const foo = let
    y = zeros(100)
    function inner_foo(x)
        for i in 1 : 100
            y[i] = 2*x[i] - 1
        end
        do_something(y)
    end
end

总结:是否使用 let 块的决定主要取决于您必须在 global 范围内可见的内容(因为 let 中定义的内容在 let 中不可见全局范围),如果您使用 let 块,最好定义要用作 let 块定义的一部分的变量。