朱莉娅发电机中的类型不稳定性
在试图减少通过EG使用Generator表达式计算可能性的函数生成的分配数量时,我遇到了以下行为,我不太了解。采用以下两个功能:
function testMax!(x,X,β)
xmax = 0.0
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
if x[i] > xmax
xmax = x[i]
end
end
y = 0.0
for i ∈ eachindex(x)
y += exp(x[i]-xmax)
end
return xmax, y
end
function testMaxWeird!(x,X,β)
xmax = 0.0
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
if x[i] > xmax
xmax = x[i]
end
end
y = sum(exp(x[j]-xmax) for j ∈ eachindex(x))
return xmax, y
end
两者都会生成相同的输出
using Random
Random.seed!(1234)
H = 10000;
X = rand(H,2);
β = rand(2);
x = zeros(H);
testMax!(x,X,β)
x = zeros(H);
testMaxWeird!(x,X,β)
返回(1.0772897308017204,6101.682959406999)。但是,第一个是类型稳定的,而第二个则不是(因此要慢得多)。
@code_warntype testMax!(x,X,β)
@code_warntype testMaxWeird!(x,X,β)
特别是,问题在于y
和xmax
的类型,输出的差异位于
y::Float64
xmax::Float64
@code_warntype
y::Any
xmax@_9::Core.Box
混淆了为什么会发生这种情况,以及是否是由于我如何在功能中多次定义xmax
的错误练习,还是我使用生成器表达式的方式?
编辑/随访所
提供的参考和解决方案非常有帮助。我仍然有些困惑,因为何时可以预期发生这种情况 - 这是由于xmax
在For-loop中更新的方式,其范围与定义的任何其他局部变量不同。在功能中?为什么(例如(效率较低)计算最大值的方法不会导致相同的封闭问题?
function testMax2!(x,X,β)
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
end
xmax = maximum(x)
y = sum(exp(x[j]-xmax) for j ∈ eachindex(x))
return xmax, y
end
编辑2 :没关系,我认为性能提示说明了这一点:“解析器将其转换为较低级别的说明时,通过将内部函数提取到单独的代码块来实质上重新组织上述代码。”我认为这意味着它来自多次分配的变量,以便代码的“重新排序”可能导致混乱。
While trying to reduce the number of allocations generated by a function computing a likelihood by e.g. using Generator expressions, I came across the following behavior which I do not quite understand. Take the following two functions:
function testMax!(x,X,β)
xmax = 0.0
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
if x[i] > xmax
xmax = x[i]
end
end
y = 0.0
for i ∈ eachindex(x)
y += exp(x[i]-xmax)
end
return xmax, y
end
function testMaxWeird!(x,X,β)
xmax = 0.0
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
if x[i] > xmax
xmax = x[i]
end
end
y = sum(exp(x[j]-xmax) for j ∈ eachindex(x))
return xmax, y
end
Both generate the same output
using Random
Random.seed!(1234)
H = 10000;
X = rand(H,2);
β = rand(2);
x = zeros(H);
testMax!(x,X,β)
x = zeros(H);
testMaxWeird!(x,X,β)
returns (1.0772897308017204, 6101.682959406999). However, the first one is type stable, while the second one is not (and therefore much slower).
@code_warntype testMax!(x,X,β)
@code_warntype testMaxWeird!(x,X,β)
In particular, the problem lies with the type of y
and xmax
, the difference in the outputs being in the @code_warntype
lines
y::Float64
xmax::Float64
versus
y::Any
xmax@_9::Core.Box
I am just confused as of why exactly this occurs, and whether it is due to bad practice on how I am defining xmax
multiple times within the function, or to the way I am using the Generator expression?
Edit/Follow-up
The references and solutions provided are very helpful. I am still somewhat confused as to when exactly this can be expected to happen -- is it due to the way that xmax
is updated within the for-loop, is its scope different from any other local variable defined within the function? Why does e.g. the (less efficient) way of computing the max not lead to the same closure issue?
function testMax2!(x,X,β)
@inbounds for i ∈ eachindex(x)
x[i] = X[i,2] * β[1] + X[i,2] * β[2]
end
xmax = maximum(x)
y = sum(exp(x[j]-xmax) for j ∈ eachindex(x))
return xmax, y
end
Edit 2: Nevermind, I think the Performance Tips explain this: "The parser, when translating it into lower-level instructions, substantially reorganizes the above code by extracting the inner function to a separate code block." I assume that this means that it comes from the variable being assigned multiple times such that the "reordering" of the code might lead to confusion.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
在创建一些封闭时,这是一个长期存在的问题的变化, https://github.com/julialang/朱莉娅/问题/15276 。
This is a variation on a longstanding issue when creating some closures https://github.com/JuliaLang/julia/issues/15276.