为什么在广播分配给预分配数组的过程中会发生分配?

问题描述 投票:0回答:1

我无法理解为什么分配是在广播分配期间发生的,其中涉及的所有操作本身都是广播的。

using TimerOutputs
to = TimerOutput()

function f(to::TimerOutput)
    k = 100
    n = 10000

    a = zeros(Int, n)
    b = zeros(Int, n)

    c = falses(n)
    d = falses(n)

    @timeit to "a" rand!(a, 1:k)
    @timeit to "b" rand!(b, 1:k)

    @timeit to "c" c .= a .<= b
    @timeit to "d" d .= c .& (b .!= 0)
end

f(to)
show(to; allocations=true, compact=true)

(请注意,

a, b, c, d
的顺序在各个表中实际上是随机的。)

                         Time          Allocations  
                   ───────────────   ───────────────
  Total measured:       111ms            12.4MiB    

 Section   ncalls     time    %tot     alloc    %tot
 ───────────────────────────────────────────────────
 a              1   28.9μs   42.4%     0.00B    0.0%
 b              1   27.8μs   40.7%     0.00B    0.0%
 d              1   7.71μs   11.3%   4.19KiB   50.0%
 c              1   3.83μs    5.6%   4.19KiB   50.0%
 ───────────────────────────────────────────────────

我希望每一行都是非分配的;它们都使用广播操作写入预先分配的数组。我认为这相当于将结果分配给目的地的 for 循环。但是

c
d
分配来执行广播分配。

如果我将

a .<= b
替换为
a <= b
c
的分配就会消失:

                         Time          Allocations  
                   ───────────────   ───────────────
  Total measured:      95.0ms            11.7MiB    

 Section   ncalls     time    %tot     alloc    %tot
 ───────────────────────────────────────────────────
 a              1   29.0μs   38.4%     0.00B    0.0%
 b              1   28.5μs   37.7%     0.00B    0.0%
 c              1   9.29μs   12.3%     0.00B    0.0%
 d              1   8.71μs   11.5%   4.19KiB  100.0%
 ───────────────────────────────────────────────────

但是我无法弄清楚如何在不手动编写循环的情况下使

d
的分配消失:

@timeit to "d" for i in eachindex(a)  # they all have the same indices; this is ok
    d[i] = c[i] && (b != 0)
end
                         Time          Allocations  
                   ───────────────   ───────────────
  Total measured:      60.0ms            3.19MiB    

 Section   ncalls     time    %tot     alloc    %tot
 ───────────────────────────────────────────────────
 b              1   33.7μs   36.1%     0.00B     - %
 a              1   33.0μs   35.3%     0.00B     - %
 d              1   25.7μs   27.5%     0.00B     - %
 c              1    959ns    1.0%     0.00B     - %
 ───────────────────────────────────────────────────

我在导致分配的广播版本中哪里出了问题?

arrays performance julia allocation
1个回答
0
投票

我认为这只是时机的产物。使用 BenchmarkTools 这些都显示零分配:

using BenchmarkTools
let
    k = 100
    n = 10000
    a = zeros(Int, n)
    b = zeros(Int, n)
    c = falses(n)
    d = falses(n)

    @btime rand!($a, 1:$k)
    @btime rand!($b, 1:$k)

    @btime $c .= $a .<= $b
    @btime $d .= $c .& ($b .!= $0)
end;
© www.soinside.com 2019 - 2024. All rights reserved.