Splatting of an integer

Hello everyone,

I was trying to write some generic code in which users can provide indices either as Ints (in 1D) or as tuples of Ints (in 2D/3D). To interface with functions like getindex, my solution was to splat the indices.
Splatting a tuple has no runtime cost, since the compiler knows the size of the tuple. I would have expected the same to hold for integers, but I noticed a 100x runtime increase.

using BenchmarkTools

a = [1 2 3 4; 5 6 7 8]
i = (1, 2)
@btime getindex($a, ($i)[1], ($i)[2])
@btime getindex($a, ($i)...)
#=
  2.367 ns (0 allocations: 0 bytes)
  2.073 ns (0 allocations: 0 bytes)
=#

a = [1, 2, 3, 4, 5, 6]
i = 3
@btime getindex($a, $i)
@btime getindex($a, ($i)...)
#=
  1.781 ns (0 allocations: 0 bytes)
  100.659 ns (2 allocations: 32 bytes)
=#

My guess is that the same compiler optimization could be used for Ints and Tuples, but the developers did not take the time to implement it for Ints since it has little practical use. Is that correct or am I missing something?

Anyway, it is always possible to go around this limitation by converting the Int to a one-element Tuple:

i = (3,)
@btime getindex($a, ($i)[1])
@btime getindex($a, ($i)...)
#=
  1.781 ns (0 allocations: 0 bytes)
  1.782 ns (0 allocations: 0 bytes)
=#

Related discussion: Concerns about splatting

Looks like this discrepancy is gone on version 1.6:

1.5:

julia> mancellin2(a, i) = getindex(a, i...)

julia> @btime mancellin2(a, i) setup = (a = [1 2 3 4; 5 6 7 8]; i = (3, ))
  1.971 ns (0 allocations: 0 bytes)

julia> @btime mancellin2(a, i) setup = (a = [1 2 3 4; 5 6 7 8]; i = 3)
  139.657 ns (2 allocations: 32 bytes)

1.6:

julia> @btime mancellin2(a, i) setup = (a = [1 2 3 4; 5 6 7 8]; i = (3, ))
  1.981 ns (0 allocations: 0 bytes)

julia> @btime mancellin2(a, i) setup = (a = [1 2 3 4; 5 6 7 8]; i = 3)
  1.972 ns (0 allocations: 0 bytes)
2 Likes

One thing you should consider is using StaticArrays, which are like tuples, but have an algebra.

1 Like

Good point, StaticArrays are awesome. But splatting is costlier than with tuples (at least in version 1.5, maybe it has also been fixed in version 1.6).

Great! Thank you for trying this out. And thanks to the developers for fixing my issues before I know I have them :slight_smile: