gpt4 book ai didi

用于两个矩阵相加的 Julia 内存分配

转载 作者:行者123 更新时间:2023-12-04 05:37:15 25 4
gpt4 key购买 nike

我很好奇为什么 Julias 的矩阵加法实现似乎会复制。这是一个例子:

foo1=rand(1000,1000)
foo2=rand(1000,1000)
foo3=rand(1000,1000)

julia> @time foo1=foo2+foo3;
0.001719 seconds (9 allocations: 7.630 MB)
julia> sizeof(foo1)/10^6
8.0

分配的内存量与这些维度的矩阵所需的内存量大致相同。

看起来为了处理 foo2+foo3 内存被分配来存储结果,然后 foo1 通过引用分配给它。

这是否意味着对于大多数线性代数运算,我们需要直接调用 BLAS 和 LAPACK 函数来完成工作?

最佳答案

要了解这里发生了什么,让我们考虑一下 foo1 = foo2 + foo3实际上确实如此。

  • 首先它评估 foo2 + foo3 .为此,它将分配一个新的临时数组来保存输出
  • 然后它将绑定(bind)名称foo1到这个新的临时数组,取消您为预分配输出数组所做的所有努力。

  • 简而言之,您会看到内存使用量与结果数组的使用量差不多,因为该例程确实为该大小的数组分配了新内存。

    以下是一些替代方案:
  • 写一个循环
  • 使用 broadcast!
  • 我们可以尝试做 copy!(foo1, foo2+foo3)然后您预先分配的数组将被填充,但它仍会分配临时(见下文)
  • 原版贴在这里

  • 这是这 4 种情况的一些代码
    julia> function with_loop!(foo1, foo2, foo3)
    for i in eachindex(foo2)
    foo1[i] = foo2[i] + foo3[i]
    end
    end

    julia> function with_broadcast!(foo1, foo2, foo3)
    broadcast!(+, foo1, foo2, foo3)
    end

    julia> function with_copy!(foo1, foo2, foo3)
    copy!(foo1, foo2+foo3)
    end

    julia> function original(foo1, foo2, foo3)
    foo1 = foo2 + foo3
    end

    现在让我们计时这些功能
    julia> for f in [:with_broadcast!, :with_loop!, :with_copy!, :original]
    @eval $f(foo1, foo2, foo3) # compile
    println("timing $f")
    @eval @time $f(foo1, foo2, foo3)
    end
    timing with_broadcast!
    0.001787 seconds (5 allocations: 192 bytes)
    timing with_loop!
    0.001783 seconds (4 allocations: 160 bytes)
    timing with_copy!
    0.003604 seconds (9 allocations: 7.630 MB)
    timing original
    0.002702 seconds (9 allocations: 7.630 MB, 97.91% gc time)

    你可以看到 with_loop!broadcast!做同样的事情,两者都比其他人更快,更高效。 with_copy!original既慢又使用更多内存。

    一般来说,要进行就地操作,我建议从编写循环开始

    关于用于两个矩阵相加的 Julia 内存分配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35465766/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com