将参数传递给函数而不在JULIA-LANG中复制它们 [英] Passing arguments to functions without copying them in JULIA-LANG

查看:54
本文介绍了将参数传递给函数而不在JULIA-LANG中复制它们的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我需要创建一个巨大的数组,并在程序中的另一个函数中使用它.我想做到这一点,而不必每次使用时都复制此数组.我知道,如果我只是简单地给他们提供参数,Julia就会有一个按共享调用的机制,并且不会复制参数.但是,如果我执行以下操作,它是否仍可以运行而无需在循环中每次都创建副本?:

function main()
    huge_arr = ones(Float32,20000,30000)
    another_arr = rand(4,5)
    coupled_var = (huge_arr,another_arr)
    for i=1:100  
        target_function(coupled_var)
    end
end

function target_function(x)
   my_first_var = x[1]
   my_second_var = x[2] 
   # some operations here 
end

解决方案

您正在处理可变对象(声明为mutable struct Array{...} ...)的数组,因此通过引用语义进行传递.

function target_function(x)
   my_first_var = x[1]        # x[1],x[2] are _mutable_ objects 
   my_second_var = x[2]       # -> this only create a new binding (no copy)
   # some operations here 
end

您可以使用my_first_var和x[1]指向同一对象. ="noreferrer"> pointer_from_objref .

示例:

function foo(x) 
   y = x
   println("Check ptr $(pointer_from_objref(x) == pointer_from_objref(y)) x:$(pointer_from_objref(x)) y:$(pointer_from_objref(y))")
end

然后尝试:

x=4.5
foo(x)
Check ptr false x:Ptr{Void} @0x00007f25a28a2850 y:Ptr{Void} @0x00007f25a28a2860

->对于Float64,y = x执行复制

x=rand(5)
foo(x)
Check ptr true x:Ptr{Void} @0x00007f25a284a410 y:Ptr{Void} @0x00007f25a284a410

->对于数组,y = x执行复制(共享相同的内存地址)

注意:在您的target_function中,请注意使用组件级操作,例如my_first_var .*= 2,因为类似my_first_var *= 2 的操作会创建一个新变量.

例如:

julia> pointer_from_objref(x)
Ptr{Void} @0x00007f25a043f890   <-
                                  |
julia> x *= 2                     |
5-element Array{Float64,1}:
 3.81254
 3.60607
 2.86026
 1.94396
 2.91994                        different memory
                                  |
julia> pointer_from_objref(x)     |
Ptr{Void} @0x00007f25a0afa210  <--|
                                  |
julia> x .*= 2
5-element Array{Float64,1}:
 7.62507
 7.21214
 5.72052
 3.88793
 5.83987                     same memory
                                 |
julia> pointer_from_objref(x)    |
Ptr{Void} @0x00007f25a0afa210 <--|

let's say I need to create one huge array and use it during my program inside another function. I want to do this without copying this array every time I use it. I know that if I simply give them as argument Julia has a call-by-sharing mechanism and it won't copy the arguments. But if I do something as following, will it still be able to operate without creating copies every time in the loop ?:

function main()
    huge_arr = ones(Float32,20000,30000)
    another_arr = rand(4,5)
    coupled_var = (huge_arr,another_arr)
    for i=1:100  
        target_function(coupled_var)
    end
end

function target_function(x)
   my_first_var = x[1]
   my_second_var = x[2] 
   # some operations here 
end

解决方案

You are manipulating Arrays that are mutable objects (declared as mutable struct Array{...} ...), hence there are passed by reference semantics.

function target_function(x)
   my_first_var = x[1]        # x[1],x[2] are _mutable_ objects 
   my_second_var = x[2]       # -> this only create a new binding (no copy)
   # some operations here 
end

You can check that my_first_var and x[1] are pointing on the same object using pointer_from_objref.

Examples:

function foo(x) 
   y = x
   println("Check ptr $(pointer_from_objref(x) == pointer_from_objref(y)) x:$(pointer_from_objref(x)) y:$(pointer_from_objref(y))")
end

then try:

x=4.5
foo(x)
Check ptr false x:Ptr{Void} @0x00007f25a28a2850 y:Ptr{Void} @0x00007f25a28a2860

-> for a Float64, y=x performs a deep copy

x=rand(5)
foo(x)
Check ptr true x:Ptr{Void} @0x00007f25a284a410 y:Ptr{Void} @0x00007f25a284a410

-> for an array, y=x performs a shallow copy (share same memory address)

Note: in your target_function take care of using component level operations, like my_first_var .*= 2 because something like my_first_var *= 2 creates a new variable.

For instance:

julia> pointer_from_objref(x)
Ptr{Void} @0x00007f25a043f890   <-
                                  |
julia> x *= 2                     |
5-element Array{Float64,1}:
 3.81254
 3.60607
 2.86026
 1.94396
 2.91994                        different memory
                                  |
julia> pointer_from_objref(x)     |
Ptr{Void} @0x00007f25a0afa210  <--|
                                  |
julia> x .*= 2
5-element Array{Float64,1}:
 7.62507
 7.21214
 5.72052
 3.88793
 5.83987                     same memory
                                 |
julia> pointer_from_objref(x)    |
Ptr{Void} @0x00007f25a0afa210 <--|

这篇关于将参数传递给函数而不在JULIA-LANG中复制它们的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆