Are broadcast-assignment and `copyto!` safe with aliasing?

Are broadcast-assignment and copyto! between two AbstractVector objects guaranteed to be safe if the two vectors alias each other (in a non-crazy way)? I’m especially interested if copying from an array into itself is guaranteed to be a no-op:

a .= a
copyto!(a, a)

Or do I have to prefix that with an explicit check?

if a !== b
    copyto(a, b)
end

Would the compiler be able to figure out that copyto!(a, a) is exactly a no-op? That is, should I use the check in my code for performance reasons, even if the copyto! itself is safe?

In my application, I probably don’t need other types of aliasing than the vectors being identical, so anything beyond that is more of a curiosity. I’m definitely not interested in “crazy” aliasing, e.g. if b is an AbstractVector that is some permuted view of a. I think what I’m asking is whether I can assume that broadcast-assignment and copyto! work equivalently to

function copyto!(a, b)
    for i in eachindex(b)
        a[i] = b[i]
    end
end

(ignoring that a and b might have different indices; you get the point).

1 Like

There’s two questions here:

  1. Will aliasing cause semantic differences in the values it returns?
  2. Will aliasing cause performance differences in the runtime?

The answer to (1) will depend on the exact method. On Julia v1.11, most ! functions have explicit warnings about unexpected behaviors if the output aliases with any of the inputs — and copyto! is no exception. Broadcasted assignments do attempt to avoid introducing unexpected behaviors when the destination aliases any of the inputs, but they do so by making preventative copies at the expense of performance.

So, yes, aliasing can cause performance differences — but often to your detriment.

2 Likes