"Scalarizing" an element in broadcast or dot fused calls


#1

Just thought I might share this … even if its probably trivial for most of you.

Let assume you have a 3x3 matrix and vector of n length 3 vectors

K = rand(3,3)
V = [rand(3) for i=1:1000]

and you want to multiply K with each element of V

K .* V
or
broadcast(*,K,V)

will not work due to DimensionMismatch error

but this does work:
[K] .* V
broadcast(*,[K],V)

trivial but nice


#2

The slightly cheaper way is (K,). Base.RefValue is also expected to work.


#3

i.e. Ref(K) .* V


#4

You gotta admit that [K] .* V
Is better on the eyes than (K,) .* V which is slightly more cryptic.
I’ll keep in mind the slight performance gain though.


#5

Interestingly using Ref is about 3 times faster

julia> @btime  Ref($K) .* $(V);
  26.449 μs (1001 allocations: 117.31 KiB)

julia> @btime  [$K] .* $(V);
  81.320 μs (1003 allocations: 117.42 KiB)

julia> @btime  ($K,) .* $(V);
  85.267 μs (2001 allocations: 132.94 KiB)

#6

I thought Ref was something for the foreign function interface (based on this), but apparently it has other roles. Where is this documented? I would like to read about it.


#7

It is really interesting because I would expect broadcast to “peel” the outer layer, and that the only performance difference would come from that.

But apparently this scales with the size of V.
Weird