【问题标题】:what's the fastest way to reset a julia array to all zeros?将 julia 数组重置为全零的最快方法是什么?
【发布时间】:2017-01-27 03:47:15
【问题描述】:

假设我有一个像这样的现有数组

x = rand(4)

然后我想将x 重置为零。我可以避免做x = zeros(4)。我担心内存分配。

【问题讨论】:

    标签: arrays memory julia


    【解决方案1】:

    你可以的

    fill!(x, 0.0)
    

    这会用零覆盖内容。

    不过,这应该与执行 for 循环一样有效:

    for i in 1:length(x)
        x[i] = 0.0
    end
    

    确实,如果你使用@edit fill!(x, 0.0),你会发现它基本上是这样做的(除了它使用@inbounds 来提高效率)。

    【讨论】:

      【解决方案2】:

      最好的办法是:

      x .= zero(y)
      

      fill!(x, zero(y))
      

      y 是您想要的数字类型。这种方式之所以好的原因是它适用于所有情况。如果x 是任何类型,只要y 匹配该类型,就可以使用它(实际上,您可以使用y = x[1])。

      当我指的是任何类型时,我的意思是这也适用于像 SIUnits 这样的奇数类型。如果你使用这个命令,一个包可以支持 SIUnits 而无需导入包,因为这会将正确的单位应用于x 值(只要它的所有操作在单位中都是正确的),而fill!(x, 0.0) 将由于单位错误而导致的错误(您也可以使用fill!(x, zeros(y))。否则,您必须检查单位和各种东西。

      【讨论】:

      • 实际上fill!(x, 0.0) 进行了自动转换,并且显然可以正常工作。无论如何,fill!(x, zero(eltype(x))) 会更加连贯,因为结果必须与x 的元素类型具有相同的类型,因为它被放回同一个数组中。
      • fill!(x, 0) 依赖于能够将 0 转换为正确的类型。在某些情况下,这是无法做到的。例如,您不能将 0(无量纲)转换为 0meters。另一个是RGB 值的向量,其中将标量转换为 RGB 值是不明确的。
      • 在 Julia 0.5 中,您也可以使用 x .= 0。请注意,所有这三个方法实际上都在后台调用 fill!
      【解决方案3】:

      在我看来,人们似乎提出了很好的替代方法,但没有人解决“什么是最有效的方法(特别是在内存方面)”的实际问题。

      原来如此。给定:

      f1(x) = x    = zeros(size(x));
      f2(x) = x[:] = zero(x[1]);
      f3(x) = fill!(x, zero(x[1]));
      f4(x) = x    = zero(x);
      

      我们有:

      julia> x=rand(1000,1000); @time (for i in 1_000_000_000; x=f1(x); end;)
        0.000715 seconds (3 allocations: 7.629 MB)
      

      julia> x=rand(1000,1000); @time (for i in 1_000_000_000; f2(x); end;)
        0.000691 seconds (2 allocations: 32 bytes)
      

      julia> x=rand(1000,1000); @time (for i in 1_000_000_000; f3(x); end;)
        0.000702 seconds (2 allocations: 32 bytes)
      

      julia> x=rand(1000,1000); @time (for i in 1_000_000_000; x=f4(x); end;)
        0.000704 seconds (2 allocations: 7.629 MB)
      


      PS。作为对下面一些 cmets 的回应,上述方法的比较纯粹是为了说明方法的区别定量,而不是笼统的抽象术语,以便更充分地解决“还有什么”的问题效率,多少”等。
      这并不意味着 f1f4mutating 函数;它们不是,它们返回对内存中新对象的引用;即他们在那里是为了完整地展示 OP 可能试图避免的 bad 替代方案。

      我只是觉得关于“效率”的问题值得一些数字来补充我同事提出的建议:)

      【讨论】:

      • f1f4 不要做你想让他们做的事。
      • x[:]! 都是就地语法(嗯,! 是约定),因此它们不会有任何临时性。因此,它们是相同的也就不足为奇了。 x = zero(x)x = zeros(length(x)) 是返回向量的向量函数,因此它们分配并不奇怪。我不知道你还想在这里展示什么。
      • @Matt:我知道 f1(我现在编辑它以保持一致),但为什么是 f4?需要详细说明吗?
      • @ChrisRackauckas 我并没有暗示这会令人惊讶。这只是一个比较。 OP 担心内存分配,我将分配和就地操作的情况都放在了显示一些数字上。至于x[:]fill! 并不奇怪,它们没有任何临时变量,因此它们是相同的,嗯,这是真的,但也不能保证。我们可以随心所欲地谈论理论,但基准可以消除所有疑问,不是吗? :)
      • f1f4 都不会修改函数的参数。他们都创建了一个全新的数组,并且碰巧将其命名为与函数参数相同的名称。但这只是改变了名称 x 在函数的本地范围内指向的内容;它对调用函数的数组没有任何影响。
      猜你喜欢
      • 2012-02-27
      • 1970-01-01
      • 2023-03-08
      • 2014-07-12
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多