Reputation: 1008
I want to multiply each row of the matrix A by the same vector v. For example
A =[1.0 3.0; 1.0 1.0]
v = [1.0, 2.0]
I would like to output
[1.0 6.0; 1.0 2.0]
So far I am doing:
(v.*A')'
But I doubt this is computationally efficient given that I transpose a matrix twice.
As a note this question was answered for Matlab (https://uk.mathworks.com/matlabcentral/answers/243307-vector-matrix-multiplication-row-wise)
Upvotes: 5
Views: 4344
Reputation: 10127
You have at least the following options:
(v.*A')'
(OP's suggestion)v'.*A
(shortest way)mapslices(row->v.*row, A, 2)
i.e.
function tt(v, A)
r = similar(A)
@inbounds for j = 1:size(A,2)
@simd for i = 1:size(A,1)
r[i,j] = v[j] * A[i,j] # fixed a typo here!
end
end
r
end
Speed comparison (in ascending order)
julia> @btime tt($v,$A); # @AborAmmar's answer
38.826 ns (1 allocation: 112 bytes)
julia> @btime ($v)'.*$A;
49.920 ns (1 allocation: 112 bytes)
julia> @btime (($v).*($A)')';
123.797 ns (3 allocations: 336 bytes)
julia> @btime mapslices(row->($v).*row, $A, 2);
25.174 μs (106 allocations: 5.16 KiB)
EDIT: Took more careful and faster manual implementation from @AborAmmar's post (replaced old one) and updated speed comparison.
Upvotes: 5
Reputation: 5559
What is really awesome about Julia is that you can create your own functions with the same performance as highly optimized builtin functions. Here is another implementation with the same performance (or slightly better) as (v' .* A)
:
function tt1(v, A)
v'.*A
end
function tt(v, A)
r = similar(A)
@inbounds for j = 1:size(A,2)
@simd for i = 1:size(A,1)
r[i,j] = v[j] * A[i,j]
end
end
r
end
const n = 10^4
const A = rand(n,n)
const v = rand(n)
@time tt1(v, A);
@time tt(v, A);
0.283537 seconds (6 allocations: 762.940 MiB, 19.70% gc time)
0.235699 seconds (6 allocations: 762.940 MiB, 0.44% gc time)
Upvotes: 3