Цикл For кажется быстрее, чем матричная операция

Некоторое время я работал над логитами, для чего мне нужно использовать встроенную функцию exp (). Кажется, что это работает медленнее для большой матрицы по сравнению с использованием цикла for с меньшими фрагментами той же матрицы.

В документации Matlab и некоторых других формах всегда рекомендуется векторизовать код, чтобы ускорить его. Но, похоже, здесь дело обстоит не так.

n = 32;
rows = 50000;
cols = 32;

a = rand(n*rows, cols);
b = rand(rows, cols);

% in a loop
tic
for i=1:n 
   d = exp(b);
end
toc

% big matrix
tic
d = exp(a);
toc

Я ожидал, что первый крестик будет медленнее, чем второй. Но результат был таким:

Elapsed time is 0.335781 seconds.
Elapsed time is 0.390191 seconds.

Любая идея относительно того, почему это так, будет полезна.

Изменить 1. Допустим, я редактирую свой код следующим образом, чтобы каждый раз использовать случайные значения:

n = 32;
rows = 50000;
cols = 32;

% in a loop
tic
for i=1:n 
   d = exp(rand(rows, cols));
end
toc

% big matrix
tic
e = exp(rand(n*rows, cols));
toc
return

Я все еще получаю:

Elapsed time is 0.745808 seconds.
Elapsed time is 0.847162 seconds.

person Chaitanya Baweja    schedule 22.03.2019    source источник


Ответы (1)


Вы не проводите честного сравнения: ваш случай «цикла» использует гораздо меньше памяти, много раз читая один и тот же меньший массив, по сравнению со случаем «большой матрицы», который читает гораздо больший кусок памяти и записывает в гораздо больший кусок памяти. Чтение из основной памяти является узким местом, поэтому возможность использования кеша помогает ускорить выполнение кода цикла.

Это более справедливое сравнение:

rows = 32*50000;
cols = 32;

a = rand(rows, cols);

% in a loop
tic
d = zeros(size(a));
for i=1:cols
   d(:,i) = exp(a(:,i));
end
toc

% big matrix
tic
d = exp(a);
toc

Я вижу (MATLAB R2019a Online):

Elapsed time is 0.208699 seconds.
Elapsed time is 0.140489 seconds.

Таким образом, цикл медленнее. Но это не намного медленнее. За последние 15 лет или около того MATLAB неуклонно совершенствовал свой JIT. До того, как они представили JIT, код цикла был бы в ~ 100 раз медленнее.

NB: всегда проверяйте, чтобы сценарий времени запускался не менее двух раз, отбрасывайте первые тайминги. При первом запуске кода JIT необходимо его скомпилировать, увеличив измеренное время.


Что касается редактирования 1:

Здесь вы все еще имеете дело с меньшими массивами в случае "цикла". Не так много изменений, за исключением того, что вы переместили вызов rand внутри цикла. Временная память используется повторно.

person Cris Luengo    schedule 22.03.2019
comment
Я понимаю вашу точку зрения, но я чувствовал, что, поскольку меньшая матрица все еще работает n раз, она должна быть намного медленнее. Не будут ли операции чтения и записи повторяться столько раз? - person Chaitanya Baweja; 23.03.2019
comment
@ChaitanyaBaweja: Я не думаю, что там много изменений. Смотрите мою правку. - person Cris Luengo; 23.03.2019