【问题标题】:Broadcast operator over field of an array of structures (Julia)结构数组字段上的广播运算符(Julia)
【发布时间】:2019-04-12 23:10:33
【问题描述】:

我有一个数组实例化结构(相同类型)。我想更改这些结构的某个字段的值。出于性能原因,我想避免使用 for 循环。这是一个玩具代码来说明我的工作:

mutable struct foo
    x
end

a,b = foo(5), foo(7)

arr = [a,b]

.-(getfield.(arr,:x),1)

我希望这会将 x 字段放入一个数组(指向实际 foo 的实际 x 字段的指针),然后将 -1 应用于所有这些。 当我打电话给a,b 时,它们没有改变。调试后我知道这是因为getfield 的broadcast() 将(Broadcast.materialize)字段具体化为一个新数组,即被复制。

有没有合适且高效的方法来做到这一点而无需循环?

谢谢

【问题讨论】:

  • 为什么不循环?它们同样快(如果不是更快的话)而且非常简单。
  • 有人告诉我矢量化表达式更快。我不记得在哪里,但是有一些 sum() 的演示比矢量化表达式慢得多。不是吗?我认为这是因为广播减少了内存分配或其他原因(我是业余爱好者,所以我肯定是错的)。
  • 这篇旧帖子确实说它们应该更快,但事实并非如此(在 0.6 中,我使用 1.1)。 Link
  • this 也建议这样做,来自 julialang.org
  • 我通常是这样想的。 1) Julia 中的循环很快。 2) Julia 中的广播足够聪明,可以相当快。有时广播可能比写得不好的循环更快(例如,当 SIMD 操作可能时),但一般来说,正确编写的循环总是很快。

标签: julia broadcast


【解决方案1】:

循环应该很快,正如Matt B. 所指出的那样。但是,如果你想避免循环(主要是为了方便),你可以写:

foreach(v -> v.x -= 1, arr)

(实际上是一种循环,但我不希望它比循环快)

或使用StructArrays.jl,根据我的经验,这非常棒。你想要的可以实现,例如像这样(使用你的arr):

using StructArrays
arr2 = StructArray(arr)
arr2.x .-= 1

并且 StructArrays.jl 会小心地从 x 字段中的 arr2 的所有元素中减去 1

EDITfor 循环结构集合相比,如果您执行按列操作,您可以预期StructArray 有时会更快(在您的示例中,该字段的类型为@ 987654331@ 所以这应该是不相关的,但如果它有例如类型 Int 并且结构有很多字段,你会注意到差异)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多