Рассмотрим следующий простой тест скорости для arrayfun
:
T = 4000;
N = 500;
x = randn(T, N);
Func1 = @(a) (3*a^2 + 2*a - 1);
tic
Soln1 = ones(T, N);
for t = 1:T
for n = 1:N
Soln1(t, n) = Func1(x(t, n));
end
end
toc
tic
Soln2 = arrayfun(Func1, x);
toc
На моей машине (Matlab 2011b на Linux Mint 12) вывод этого теста:
Elapsed time is 1.020689 seconds.
Elapsed time is 9.248388 seconds.
Что??? arrayfun
, хотя, по общему признанию, более чистое решение, на порядок медленнее. Что здесь происходит?
Кроме того, я сделал аналогичный стиль теста для cellfun
и обнаружил, что он примерно в 3 раза медленнее, чем явный цикл. Опять же, этот результат противоположный тому, что я ожидал.
Мой вопрос: Почему arrayfun
и cellfun
намного медленнее? И учитывая это, есть ли веские причины их использовать (кроме того, чтобы код выглядел хорошо)?
Примечание.. Я говорю о стандартной версии arrayfun
здесь, а не о версии GPU из панели инструментов параллельной обработки.
EDIT: Чтобы быть ясным, я знаю, что Func1
выше может быть векторизован, как указал Оли. Я выбрал его только потому, что он дает простой тест скорости для целей фактического вопроса.
РЕДАКТИРОВАТЬ: Следуя предложению grungetta, я повторил тест с feature accel off
. Результаты:
Elapsed time is 28.183422 seconds.
Elapsed time is 23.525251 seconds.
Другими словами, будет казаться, что большая часть разницы заключается в том, что ускоритель JIT делает гораздо лучшую работу по ускорению явного цикла for
, чем при использовании arrayfun
. Это кажется мне странным, так как arrayfun
фактически предоставляет больше информации, т.е. Его использование показывает, что порядок вызовов Func1
не имеет значения. Кроме того, я отметил, что включение или выключение ускорителя JIT, моя система использует только один процессор...