Почему векторный код работает быстрее, чем для циклов в MATLAB?

Я читал этот, но я до сих пор не понимаю, почему векторизованный код работает быстрее.

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

Ответ 1

Нет. Вы смешиваете две важные концепции:

  • MATLAB предназначен для быстрого выполнения векторных операций. MATLAB - интерпретируемый язык, поэтому циклы настолько медленны в нем. MATLAB оборачивает эту проблему, предоставляя чрезвычайно быстрый (обычно написанный на C и оптимизированный для конкретной архитектуры) и хорошо проверенные функции для работы с векторами. Здесь нет никакой магии, это всего лишь куча тяжелой работы и много лет постоянных небольших улучшений.

Рассмотрим, например, тривиальный случай, такой как:

s=0;
for i=1:length(v),
    s = s+v(i);
end

и

sum(v)

вы должны, вероятно, использовать tic и toc ко времени этих двух функций, чтобы убедить себя в разнице во времени выполнения. Существует около 10 аналогичных широко используемых функций, которые работают на векторах, примеры: bsxfun, repmat, length, find. Векторизация является стандартной частью эффективного использования MATLAB. Пока вы не сможете эффективно векторизовать код, вы просто турист в мире MATLAB, а не гражданин.

  • Последние версии MATLAB предоставляют parfor. parfor не является серебряной пулей, это инструмент, который можно использовать и использовать неправильно (попробуйте parfor на примере суммы выше). Не все форты могут быть обработаны. parfor предназначен для задач-параллельных типов задач, где каждая итерация цикла не зависит друг от друга. Это ключевое требование для использования parfor-loop.

Хотя во многих случаях parfor может многое помочь, тип циклов, которые могут быть обработаны для очень больших коэффициентов, происходит редко.

Ответ 2

Я согласен с carlosdc в его ответе. Тем не менее, важно помнить, что Matlab с версии 6.5 включал компилятор JIT для ускорения циклов и т.д.

Я быстро проверил пример вашей суммы с миллионом элементов в v и получил следующие результаты:

  • sum(v): 4,3 мс
  • for-loop version: 16 мс
  • for-loop version, no JIT: 966 мс

JIT можно включить и выключить следующим образом:

feature accel off
feature accel on

Фактор 4 в улучшении путем векторизации кода, конечно, все еще часто стоит того, но его нельзя опасаться, поскольку они когда-то были для проблем, где они в противном случае являются хорошим решением. Часто, хотя кусок хорошо векторизованного кода часто может быть проще, меньше ошибок и быстрее в то же время.

Ответ 3

В современных компьютерах регистры (временная память, используемая для математики, среди других применений) имеют много бит и могут манипулировать несколькими номерами вместе. Например, если ваши данные - uint8 (8 бит), вы можете добавить число к каждому из них в один процессорный такт, или вы можете поместить 8 из них в регистр, а число - ко всем из них за один такт процессора, Таким образом, вы работаете в 8 раз быстрее, чем для цикла.

Это в некотором смысле распараллеливание, но не подобное parfor. Parfor использует несколько ядер вашего процессора, и в приведенном выше методе одно ядро ​​используется более эффективно. Если вы используете их оба, вы можете достичь еще более высоких скоростей.