【问题标题】:Julia - Is there a way to make this in-place assignment function look betterJulia - 有没有办法让这个就地分配功能看起来更好
【发布时间】:2017-09-23 23:13:51
【问题描述】:

考虑一下这段代码:

q = zeros(5,5);
x = rand(5,5);
function testFunc!(n, q, x)
    for i = 1:n
        q .= x.^2;
    end
end

我初始化q 并通过就地赋值函数更新q 中的值。无论我如何选择n,分配的数量都是恒定的,因为我没有创建任何新内容。

但是,有没有办法编写一个名为 testFunc2 的函数,如下所示:

q = zeros(5,5)
x = rand(5,5);
q = testFunc2(n, x)

这样内存分配对于n是不变的。

我知道这看起来很傻,但在我的实际代码中,我有许多类似于q 的变量,并且我有一个循环在每次迭代时更新它们。我不希望代码占用过多的内存。如果我编写一个看起来像testFunc2(n, x, q1, q2, q3, q4) 的函数,它的语法看起来会很麻烦。因此,我希望能够拥有q1, q2, q3, q4 = testFunc2(n, x) 而不必担心内存。

【问题讨论】:

    标签: julia allocation


    【解决方案1】:

    如果我理解正确,最简单的方法是使用闭包:

    let 
       q1 = similar(q)
       q2 = similar(q)
       global function testFunc2(n, x)
           for i = 1:n
              q1 .= x.^2
              q2 .= x.^2
           end
           return q1, q2
       end
    end
    
    julia> @btime testFunc2(10, $x)
      786.000 ns (0 allocations: 0 bytes)
    
    julia> @btime testFunc2(100, $x)
      7.476 μs (0 allocations: 0 bytes)
    

    正如@Liso 在下面的评论中指出的那样,如果我们不尝试在调用之间共享相同的内存,则应该返回副本,例如return copy(q1), copy(q2) 而不是 return q1, q2,那么我们仍然会得到恒定的内存分配:

    @btime testFunc2(10, $x)
      821.684 ns (3 allocations: 704 bytes)
    
    @btime testFunc2(100, $x)
      7.326 μs (3 allocations: 704 bytes)
    

    无论如何,选择哪种方法取决于对应的用例,functor 是一个更灵活的选择。

    【讨论】:

    • 更多调用的结果共享相同的内存:r1 = testFunc2(10, zeros(5,5));println(r1[1][1]);r2 = testFunc2(10, ones(5,5));println(r1[1][1]) -> 0.0 1.0 这是想要的吗?
    • @Liso 这就是我写“如果我理解正确”的原因;),我的想法只是为了说明关闭的想法。我已经更新了我的答案。
    【解决方案2】:

    我不确定q1, q2, q3, q4 = testFunc2(n, x) 看起来是否比testFunc2!(n, x, q1, q2, q3, q4) 好很多,但您可以使用这样的宏进行这种类型的转换:

    macro wrap(ex)
        outputs = ex.args[1].args
        ex.args[2].args[1] = Symbol(ex.args[2].args[1], "!")
        append!(ex.args[2].args, outputs)
        esc(ex)
    end
    

    展开

    @wrap q1, q2, q3, q4 = testFunc2(n, x)
    

    进入

    (q1, q2, q3, q4) = testFunc2!(n, x, q1, q2, q3, q4)
    

    【讨论】:

    • 不错! :) 如果真的是为了好看,那么testFunc3!(n, x, q...) 之类的东西可能也会有所帮助。
    猜你喜欢
    • 2012-10-07
    • 2022-09-30
    • 2020-07-29
    • 2021-07-04
    • 2015-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多