порядок следования вложенных циклов - PullRequest
0 голосов
/ 19 января 2019

Предположим, у меня есть следующий код.Это будет быстрее версия 1 или версия 2?Что меняет, так это упорядочение двух вложенных циклов

VERSION 1

% bigArray has dim: [npolv,nz,nsv]
% npolv=68961 > nsv=200 > nz=81
for j=1:nz
   for qq=1:nsv
       % the output of fun is a vector dim npolv
       bigArray(:,j,qq) = fun();
   end
end

или VERSION 2

% bigArray has dim: [npolv,nz,nsv]
% npolv=68961 > nsv=200 > nz=81
for qq=1:nsv
    for j=1:nz
        % the output of fun is a vector with dim npolv
        bigArray(:,j,qq) = fun();
    end
end

Ответы [ 2 ]

0 голосов
/ 20 января 2019

Версия 2, скорее всего, будет быстрее, чем версия 1, из-за того, что Matlab хранит данные в памяти (по столбцам или, точнее, крайний левый индекс изменяется быстрее всего и сохраняется в смежной области памяти), а также из-за эффектов кэширования памяти(который извлекает из памяти одну страницу [например, 4 КБ = 500 double элементов] за раз).Это называется пространственная локализация или принцип эталонной .Зацикливая крайний правый индекс перед левым, мы максимизируем эффективность кэша ЦП, поскольку ЦП не требуется частый доступ к основной памяти (ОЗУ) для выборки смежных элементов данных.

Эффекткак правило, маленький или незначительный для небольших матриц данных, но он может быть значительным, когда размер данных больше размера страницы вашей платформы - в таких случаях вы можете увидеть ускорение в 2 раза или даже больше с версией 2 по сравнению с версией 1.

* 1011Сказав все это, если бы вы могли сделать fun() векторизованным, потенциальные ускорения могли бы быть намного больше, чем при переключении порядка петель.
0 голосов
/ 19 января 2019

Если вы выделите вектор bigArray=zeros(DIM,nz,nsv), практической разницы нет.

В обоих случаях функция fun() выполняется nz*nsv раз, последовательно.

Вместо этого проверьте время каждой возможности с помощью tic t=toc и с использованием parfor для параллельного выполнения.

...