Почему векторный код работает быстрее, чем для циклов в 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 использует несколько ядер вашего процессора, и в приведенном выше методе одно ядро используется более эффективно. Если вы используете их оба, вы можете достичь еще более высоких скоростей.