What is the most efficient way to access (and perhaps replace) an entry in a large multidimensional array? I am using something like this inside a loop:
tup = (16,45,6,40,3)
A[tup...] = 100
but I'm wondering if there is a more efficient way. In particular, is there a way I can avoid using ...?
There's not always a penalty involved with splatting, but determining where it is efficient isn't always obvious (or easy).  Your trivial example is actually just as efficient as writing A[16,45,6,40,3] = 100.  You can see this by comparing
   function f(A)
       tup = (16,45,6,40,3)
       A[tup...] = 100
       A
   end
   function g(A)
       A[16,45,6,40,3] = 100
       A
   end
julia> code_llvm(f, Tuple{Array{Int, 5}})
# Lots of output (bounds checks).
julia> code_llvm(g, Tuple{Array{Int, 5}})
# Identical to above
If there was a splatting penalty, you'd see it in the form of allocations.  You can test for this with the @allocated macro or by simply inspecting code_llvm for a reference to @jl_pgcstack — that's the garbage collector, which is required any time there's an allocation.  Note that there is very likely other things in a more complicated function that will also cause allocations, so it's presence doesn't necessarily mean that there's a splatting pessimization. But if this is in a hot loop, you want to minimize all allocations, so it's a great target… even if your problem isn't due to splatting. You should also be using @code_warntype, as poorly typed code will definitely pessimize splats and many other operations.  Here's what will happen if your tuple isn't well typed:
   function h(A)
       tup = ntuple(x->x+1, 5) # type inference doesn't know the type or size of this tuple
       A[tup...] = 100
       A
   end
julia> code_warntype(h, Tuple{Array{Int,5}})
# Lots of red flags
So optimizing this splat will be highly dependent upon how you construct or obtain tup.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With