julia闭包中的数组分配

问题描述 投票:1回答:1

我想知道在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-array的内存只分配一次,这显着提高了性能(在我的非玩具案例中)。我想知道这样做是一种“朱利安式”吗?

arrays closures julia allocation lexical-scope
1个回答
1
投票

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

要点1.使用let的代码不会在Julia 1.0下运行,因为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

而且你会有很好的表现,因为朱莉娅1.0知道y有恒定类型并会优化它。结果是你将在全局范围内使用y并在方法表中使用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块的返回值赋给变量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块定义的一部分。

© www.soinside.com 2019 - 2024. All rights reserved.