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
块定义的一部分的变量。
我想知道在 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
块定义的一部分的变量。