From the manual, I expected both cases below to perform equally well, but that seems not to be the case:
julia> using BenchmarkTools
julia> a = [2, 3, 4, 5];
julia> b = [6 7 8 9];
julia> @benchmark a .+ b
BenchmarkTools.Trial:
memory estimate: 256 bytes
allocs estimate: 3
--------------
minimum time: 331.071 ns (0.00% GC)
median time: 335.829 ns (0.00% GC)
mean time: 362.109 ns (1.72% GC)
maximum time: 6.075 μs (91.57% GC)
--------------
samples: 10000
evals/sample: 225
julia> @benchmark broadcast(+, a, b)
BenchmarkTools.Trial:
memory estimate: 208 bytes
allocs estimate: 1
--------------
minimum time: 89.245 ns (0.00% GC)
median time: 91.958 ns (0.00% GC)
mean time: 100.715 ns (1.96% GC)
maximum time: 757.825 ns (74.58% GC)
--------------
samples: 10000
evals/sample: 958
The dot syntax is over 3x slower. A full two-fold speed-up can be gained on top of that by the use of broadcast!
:
julia> c = similar(a .+ b);
julia> @benchmark broadcast!(+, c, a, b)
BenchmarkTools.Trial:
memory estimate: 0 bytes
allocs estimate: 0
--------------
minimum time: 49.568 ns (0.00% GC)
median time: 50.333 ns (0.00% GC)
mean time: 51.231 ns (0.00% GC)
maximum time: 140.148 ns (0.00% GC)
--------------
samples: 10000
evals/sample: 988
So all those three examples seem to be doing different things. To complicate things a bit, the following seem not to be equivalent to broadcast!
:
julia> @benchmark c .= a .+ b
BenchmarkTools.Trial:
memory estimate: 48 bytes
allocs estimate: 2
--------------
minimum time: 280.375 ns (0.00% GC)
median time: 284.998 ns (0.00% GC)
mean time: 298.332 ns (0.45% GC)
maximum time: 5.007 μs (90.98% GC)
--------------
samples: 10000
evals/sample: 285
julia> @benchmark @. c = a + b
BenchmarkTools.Trial:
memory estimate: 48 bytes
allocs estimate: 2
--------------
minimum time: 281.868 ns (0.00% GC)
median time: 297.573 ns (0.00% GC)
mean time: 341.300 ns (0.42% GC)
maximum time: 5.637 μs (91.15% GC)
--------------
samples: 10000
evals/sample: 287
What’s going on here? What am I missing? Are those results valid in general? Should I always use broadcast!
?
Why does the manual say that “[d]otted operators such as .+
and .*
are equivalent to broadcast
calls (except that they fuse, as described above)”? (source)
Does that have something to do with my environment?
julia> versioninfo()
Julia Version 1.4.1
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: Intel(R) Core(TM) i7-5500U CPU @ 2.40GHz
WORD_SIZE: 64
LIBM: libopenlibm
LLVM: libLLVM-8.0.1 (ORCJIT, broadwell)
Environment:
JULIA_NUM_THREADS = 4