【问题标题】:Change in the values of global variables not immediately updated?全局变量的值变化不会立即更新?
【发布时间】:2016-01-17 04:44:49
【问题描述】:

在以下代码中,我尝试在函数test() 中修改所有全局变量(s、t、u、v)。因为u 和v 在模块内,Mod.u 和Mod.v 是只读变量,所以我尝试通过setter 函数(set_u 和set_v)更改它们的值。

s = 1
const t = 2

module Mod
u = 3
const v = 4

set_u( u_ ) = ( global u ; u = u_ )
set_v( v_ ) = ( global v ; v = v_ )
end

function test()
    global s, t

    s = "S" ; t = 200
    @show s, t

    Mod.set_u( "U" ) ; Mod.set_v( 400 )
    @show Mod.u, Mod.v
end

test()
@show s, t
@show Mod.u, Mod.v

结果(使用 Julia v0.4.0 获得)是

WARNING: redefining constant t
(s,t) = ("S",2)                          # (1)
WARNING: redefining constant v
(Mod.u,Mod.v) = ("U",4)                  # (2)
(s,t) = ("S",200)                        # (3)
(Mod.u,Mod.v) = ("U",400)                # (4)

这里,(3) 和 (4) 是我的预期结果(假设 const 只修复了变量的类型)。但我不明白为什么t 和Mod.v 的值没有在(1)和(2)中更新。我是否在更改全局变量的值方面犯了一些大错误或误解......?还是因为从函数内部或外部引用全局变量的机制不同?

【问题讨论】:

    标签: global-variables julia


    【解决方案1】:

    唯一没有在函数体中“更新”的常量是那些你标记为const的常量。

    (假设const只修复了变量的类型)

    这个假设是不正确的。虽然 Julia 确实允许您更改 const 绑定的值,但重新定义 const 变量肯定会导致问题。请注意,它警告您这不是一个好主意。

    这里有一个简单的例子来说明正在发生的事情:

    julia> const t = 3
           f() = t
    f (generic function with 1 method)
    
    julia> @code_llvm f()
    
    define i64 @julia_f_21636() {
    top:
      ret i64 3
    }
    
    julia> t = 4
           @code_llvm f()
    WARNING: redefining constant t
    
    define i64 @julia_f_21636() {
    top:
      ret i64 3
    }
    

    您无需非常精通阅读 LLVM IR 即可看到它返回整数 3 并且不进行查找。它看到t 被标记为常量,并在编译函数时使用该信息对其进行优化。打破const 并更改t 的值不会导致重新编译f,因此会返回旧值。 LLVM 对于非常量全局来说更复杂,但它仍然非常易读。你可以看到它正在从某个地方加载一个值:

    julia> s = 2
           g() = s
           @code_llvm g()
    
    define %jl_value_t* @julia_g_21649() {
    top:
      %0 = load %jl_value_t** inttoptr (i64 4417498392 to %jl_value_t**), align 8
      ret %jl_value_t* %0
    }
    

    简而言之:如果你对变量的 const-ness 撒谎,当 Julia 给你一个旧答案时,你不应该感到惊讶。

    【讨论】:

    • 啊,好吧,现在我明白了...我一直假设const 只修复变量的类型(因为它允许更改值),但这似乎很危险,因为代码编译利用假定的 constness... 我试图在 Julia 模块中使用 const 全局变量作为模拟中的“可修改参数”(遵循 Fortran 模块中的流行方式),但这似乎不是一个好主意。非常感谢:)
    • 刚刚使用 const t=[3] 作为 LLVM 优化的实用解决方法进行了测试。类型信息被保留:typeof(t[1])==Int64 并且可以更改内容。同样,这是一种变通方法,但它确实有效。
    • @user3580870 您好,我刚刚还确认您的方法有效。此外,似乎可以对 const 全局复合类型使用相同的技巧(即 Any 在其字段仍然可变时不会传播)。所以这种 const 全局类型可能对我的目的有用......但我也会尝试考虑更多“朱利安”方式来存储参数,而不是简单地从其他语言翻译。谢谢:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 2020-05-03
    • 1970-01-01
    相关资源
    最近更新 更多