Can't mul! to a slice

After watching Brian Jackson’s talk on JuliaCon 2020 Adventures in Avoiding Allocations, I wanted to try `LinearAlgebra.mul!` out. But I’m guessing that I don’t get it as `test1` and `test2` don’t yield the same result. The problem seem to arise when I want to make the “out” variable of `mul!` be a slice. Can I use `mul!` to write to an array slice?

``````julia> import LinearAlgebra

julia> function test1(A, B, n)
Y = Matrix{Float64}(undef, 2, n)
LinearAlgebra.mul!(Y[1, :], A, B)
return Y
end
test1 (generic function with 1 method)

julia> function test2(A, B, n)
Y = Matrix{Float64}(undef, 2, n)
Y[1, :] .= A * B
return Y
end
test2 (generic function with 1 method)

julia> n1 = 2
2

julia> n2 = 3
3

julia> A = rand(n2, n1)
3×2 Matrix{Float64}:
0.425788   0.748112
0.817301   0.299914
0.0576634  0.713061

julia> B = ones(n1)
2-element Vector{Float64}:
1.0
1.0

julia> Y1 = test1(A, B, n2)
2×3 Matrix{Float64}:
8.93663e-316  8.93663e-316  8.93663e-316
8.93663e-316  8.93663e-316  8.93663e-316

julia> Y2 = test2(A, B, n2)
2×3 Matrix{Float64}:
1.1739  1.11721  0.770724
0.0     0.0      0.0

julia> [Y1[1, :] Y2[1, :]]
3×2 Matrix{Float64}:
8.93663e-316  1.1739
8.93663e-316  1.11721
8.93663e-316  0.770724
``````

While I don’t understand why, the problem seems to go away if I use `view` to rewrite `test1` as

``````function test1(A, B, n)
Y = Matrix{Float64}(undef, 2, n)
LinearAlgebra.mul!(view(Y, 1, :), A, B)
return Y
end
``````

Without the view you allocate a new array that is a copy of the slice of Y, and send this to mul to store the result in. This means Y is never changed in that case. When creating the view you actually use the memory of Y corresponding to that slice to send to mul to be written to.

4 Likes