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