Confusion on performance when using the broadcasting macro @. vs explicit . operators

Indeed, ranges are often slower to access than Array(at least when arrays are small-ish and accessed in a predictable order). There are ways to make the ranges somewhat faster, however.

A big part of the cost of ranges is that they are usually TwicePrecision, giving extra accuracy (and critical to making things like 0:0.1:1 behave how you’d hope – try collect(StepRangeLen(0.0, 0.1, 11)) for comparison). But one can give this up to make things a bit faster.

julia> x = range(0, π, 100); y = StepRangeLen(first(x), step(x), length(x)); z = collect(x);

julia> typeof(x)
StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}, Int64}

julia> typeof(y) # no TwicePrecision
StepRangeLen{Float64, Float64, Float64, Int64}

julia> @btime sum(a for a in $x) # use generator to block other optimizations
  134.046 ns (0 allocations: 0 bytes)
157.07963267948963

julia> @btime sum(a for a in $y) # use generator to block other optimizations
  45.063 ns (0 allocations: 0 bytes)
157.07963267948963

julia> @btime sum(a for a in $z) # use generator to block other optimizations
  19.002 ns (0 allocations: 0 bytes)
157.07963267948963

julia> @btime sum($z) # optimized Array method using SIMD
  5.862 ns (0 allocations: 0 bytes)
157.07963267948966

julia> @btime sum(collect($x)) # the worst of both worlds
  146.022 ns (2 allocations: 928 bytes)
157.07963267948966

julia> @btime sum(collect($y)) # the worst of both worlds
  78.811 ns (2 allocations: 928 bytes)
157.07963267948966

Without TwicePrecision, the range indexing is considerably faster (but not exactly the same, although the sums coincide here). Also note that collecting a range and then iterating the Array once will virtually always be slower than simply iterating it. To see a speed benefit, you’d need to collect it once and then iterate it many times.

The reason ranges are usually recommended is that they are memory-free and that iterating them is usually either 1) much less expensive than other things you’re doing or 2) only done a few times.

3 Likes