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

В 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

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


person user61290    schedule 02.02.2015    source источник


Ответы (1)


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

Вы можете выполнить матричное умножение между 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.

person Divakar    schedule 02.02.2015
comment
@user61290 user61290 Я думаю, что это было бы лучше, учитывая, что количество умножений и суммирования будет намного меньше. - person Divakar; 02.02.2015