Allocations in broadcasted assignment (StackOverflow question)

I came across this StackOverflow post and am wondering what the solution is. I have played around with the example in this post (copied below) and, like the author, cannot get rid of the allocation in d’s broadcast assignment. Any ideas?

(A commenter says this is fixed in nightly, but I’m wondering about Julia 1.10.)

using BenchmarkTools
using Random

let
    k = 100
    n = 10000
    a = zeros(Int, n)
    b = zeros(Int, n)
    c = falses(n)
    d = falses(n)

    @btime rand!($a, 1:($k))
    @btime rand!($b, 1:($k))

    @btime $c .= $a .<= $b
    @btime $d .= $c .& ($b .!= 0)

    nothing
end

Results from the StackOverflow post:

  27.792 μs (0 allocations: 0 bytes)
  28.541 μs (0 allocations: 0 bytes)
  2.560 μs (1 allocation: 4.19 KiB)
  7.552 μs (1 allocation: 4.19 KiB)

I don’t really understand this tbh.

using BenchmarkTools
using Random
using LoopVectorization

let
    k = 100
    n = 10000
    a = zeros(Int, n)
    b = zeros(Int, n)
    c = falses(n)
    d = falses(n)

    rand!(a, 1:(k))
    rand!(b, 1:(k))

    @btime $c .= $a .<= $b    
    @btime map!(≤, $c, $a, $b)
    @btime vmap!(≤, $c, $a, $b)
    nothing
end
  3.062 μs (1 allocation: 4.19 KiB)
  22.121 μs (0 allocations: 0 bytes)
  1.236 μs (0 allocations: 0 bytes)

The allocation goes away if the destination is a Vector{Bool} instead of a BitVector, and given the 0 allocations from map!, I’d hazard a guess it’s rooted in BitArray-specific broadcasting.

2 Likes