Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Умножить две матрицы построчно

Автор вопроса: user61290Ответов: 1

В MATLAB я хочу умножить матрицу Nx4 на матрицу 4xN и получить из нее вектор Nx1. Я также делю результат поэлементно на другой вектор.

В цикле это будет:

A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
for i=1:10
    result(i)=A(i,:)*B(:,i)/L(i);
end

Единственный нециклический метод, который я могу придумать, чтобы сделать это:

A=rand(10,4);
B=rand(4,10);
L=rand(10,1);
result=diag(A*B)./L

Но это делает много ненужного умножения. Есть ли способ лучше?

matlabmatrixvectorizationmatrix-multiplication

Ответы

Ответ 1 · рейтинг 7 · Divakar

Векторизованный подход

Вы можете выполнить матричное умножение между A и транспонировать B, затем суммировать по dim-2 и, наконец, выполнить поэлементное деление с L -

result = sum(A.*B.',2)./L

Бенчмаркинг

В этом разделе рассматриваются тесты времени выполнения и ускорения для proposed approach по сравнению с loop-based approach, как указано в начале вопроса. Обратите внимание, что другой подход на основе diag, предложенный во второй части вопроса, не был охвачен в этих тестах, поскольку время выполнения с ним было сравнительно очень большим.

Код сравнительного анализа

N_arr = 4000:4000:100000;        %// Datasizes
timeall = zeros(2,numel(N_arr)); %// Array to store runtimes
for iter = 1:numel(N_arr)

    %// Create random inputs
    N = N_arr(iter);
    A=rand(N,4);    B=rand(4,N);    L=rand(N,1);

    %// Time the approaches
    f = @() mult_twomat_loopy(A,B,L);
    timeall(1,iter) = timeit(f); clear f
    f = @() mult_twomat_vect(A,B,L);
    timeall(2,iter) = timeit(f); clear f
end

%// Plot speedups
figure,hold on,grid on
plot(N_arr,timeall(1,:)./timeall(2,:),'-bo')
xlabel('Datasize, N(Rows in A)'),ylabel('Speedup Factor (x)')
title('Speedup Plot')

Связанные функциональные коды

mult_twomat_loopy.m:

function result = mult_twomat_loopy(A,B,L)
N = size(A,1);
result = zeros(N,1);
for i=1:N
    result(i)=A(i,:)*B(:,i)/L(i);
end

mult_twomat_vect.m:

function result = mult_twomat_vect(A,B,L)
result = sum(A.*B.',2)./L;

Ускорение предлагаемого подхода по сравнению с зацикленным

Выводы

Как видно из графика ускорения, предложенный подход кажется очень хорошим вариантом для решения проблемы. Интересным наблюдением из графика снова является внезапное падение производительности для предлагаемого подхода по сравнению с зацикленным подходом для 32K+ datasizes. Причиной этого провала, скорее всего, является пропускная способность системной памяти, ограничивающая производительность при таких больших размерах данных, но, к счастью, даже для таких размеров данных ускорение все еще сохраняется на отметке более 20x.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы