julia关闭中的数组分配

时间:2018-08-29 16:20:41

标签: arrays closures julia allocation lexical-scope

我想知道在包装一些功能的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数组的内存仅分配一次,这显着提高了性能(在我不是玩具的情况下)。我想知道这样做是“朱利安之道”吗?

1 个答案:

答案 0 :(得分:1)

我会给你一个朱莉娅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

,您将获得良好的性能,因为Julia 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块定义一部分的变量。