朱莉娅发电机中的类型不稳定性

发布于 2025-02-08 12:42:14 字数 1828 浏览 0 评论 0原文

在试图减少通过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,β)

特别是,问题在于yxmax的类型,输出的差异位于

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

哥,最终变帅啦 2025-02-15 12:42:14

在创建一些封闭时,这是一个长期存在的问题的变化, https://github.com/julialang/朱莉娅/问题/15276

This is a variation on a longstanding issue when creating some closures https://github.com/JuliaLang/julia/issues/15276.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文