Мой вопрос: я заметил, что многие хорошие ответы на вопросы Matlab по SO часто используют эту функцию bsxfun
. Зачем?
Мотивация: в документации Matlab для bsxfun
приведен следующий пример:
A = magic(5);
A = bsxfun(@minus, A, mean(A))
Конечно, мы могли бы сделать ту же операцию, используя:
A = A - (ones(size(A, 1), 1) * mean(A));
И на самом деле простой тест скорости показывает, что второй метод работает примерно на 20% быстрее. Так зачем использовать первый метод? Я предполагаю, что есть некоторые обстоятельства, когда использование bsxfun
будет намного быстрее, чем «ручной» подход. Мне было бы очень интересно увидеть пример такой ситуации и объяснить, почему это происходит быстрее.
Кроме того, еще один последний элемент этого вопроса, опять же из документации Matlab для bsxfun
: «C = bsxfun (fun, A, B) применяет двоичную операцию поэлементно, указанную функцией handle функции, к массивам A и B с помощью singleton расширение включено. Что означает фраза «с включенным расширением синглтона»?
tic...toc
его в строки, скорость кода будет зависеть от необходимости читать функции в памяти.timeit
функции в ссылке, которую вы / angainor / Dan предоставили.Ответы:
Я использую три причины
bsxfun
( документация , ссылка на блог )bsxfun
быстрее чемrepmat
(см. ниже)bsxfun
требует меньше печататьbsxfun
, как использованиеaccumarray
, заставляет меня чувствовать себя хорошо о моем понимании Matlab.bsxfun
будет реплицировать входные массивы вдоль их «одноэлементных измерений», то есть измерений, по которым размер массива равен 1, чтобы они соответствовали размеру соответствующего размера другого массива. Это то, что называется «одиночным экспансией». Кроме того, синглтонные измерения - это те, которые будут отброшены, если вы позвонитеsqueeze
.Вполне возможно, что для очень небольших задач этот
repmat
подход будет более быстрым, но при таком размере массива обе операции выполняются настолько быстро, что, скорее всего, это не повлияет на общую производительность. Есть две важные причиныbsxfun
, которые ускоряют: (1) вычисление происходит в скомпилированном коде, что означает, что фактическая репликация массива никогда не происходит, и (2)bsxfun
является одной из многопоточных функций Matlab.На моем прилично быстром ноутбуке я проверил сравнение скорости
repmat
иbsxfun
с R2012b.Для меня
bsxfun
это примерно в 3 раза быстрее, чемrepmat
. Разница становится более заметной, если массивы становятся большеСкачок во время выполнения
repmat
происходит вокруг размера массива 1 Мб, что может иметь какое-то отношение к размеру моего кеша процессора -bsxfun
не так уж плохо, потому что ему нужно только выделить выходной массив.Ниже вы найдете код, который я использовал для синхронизации:
источник
В моем случае, я использую,
bsxfun
потому что это мешает мне думать о проблемах столбцов или строк.Для того, чтобы написать свой пример:
Я должен решить несколько проблем:
1)
size(A,1)
илиsize(A,2)
2)
ones(sizes(A,1),1)
илиones(1,sizes(A,1))
3)
ones(size(A, 1), 1) * mean(A)
илиmean(A)*ones(size(A, 1), 1)
4)
mean(A)
илиmean(A,2)
Когда я использую
bsxfun
, я просто должен решить последний:а)
mean(A)
илиmean(A,2)
Вы можете подумать, что это ленивый или что-то, но когда я использую
bsxfun
, у меня меньше ошибок и я программирую быстрее .Более того, он короче, что улучшает скорость набора текста и удобочитаемость .
источник
Очень интересный вопрос! Я недавно наткнулся на именно такую ситуацию, отвечая на этот вопрос. Рассмотрим следующий код, который вычисляет индексы скользящего окна размером 3 через вектор
a
:В этом случае
bsxfun
почти в два раза быстрее! Это полезно и быстро, потому что позволяет избежать явного выделения памяти для матрицidx0
иidx1
сохранения их в памяти, а затем чтения их снова, чтобы просто добавить их. Поскольку пропускная способность памяти является ценным активом и часто является узким местом в современных архитектурах, вы хотите использовать ее с умом и снизить требования к памяти для своего кода, чтобы повысить производительность.bsxfun
позволяет вам сделать это: создать матрицу, основанную на применении произвольного оператора ко всем парам элементов двух векторов, вместо того, чтобы явно работать с двумя матрицами, полученными путем репликации векторов. Это одноэлементное расширение . Вы также можете думать об этом как о внешнем продукте от BLAS:Вы умножаете два вектора, чтобы получить матрицу. Просто внешний продукт выполняет только умножение и
bsxfun
может применять произвольные операторы. Как примечание, очень интересно видеть, чтоbsxfun
это так же быстро, как внешний продукт BLAS. И BLAS обычно считается доставить на работу ..Edit Благодаря комментарию Дэна, вот отличная статья Лорена, обсуждающая именно это.
источник
bsxfun
с хорошим примером.Начиная с R2016b, Matlab поддерживает неявное расширение для широкого спектра операторов, поэтому в большинстве случаев больше нет необходимости использовать
bsxfun
:Там есть подробное обсуждение о неявном расширении и его производительность на блоге Лорен. Чтобы процитировать Стива Эддинса из MathWorks:
источник
Вещи не всегда согласуются с 3 распространенными методами:
repmat
затраты на индексацию иbsxfun
. Это становится намного интереснее, когда вы увеличиваете размер вектора еще больше. Смотрите сюжет:bsxfun
на самом деле в какой-то момент становится немного медленнее, чем два других, но меня удивляет то, что если вы увеличите размер вектора еще больше (> 13E6 выходных элементов), bsxfun вдруг снова станет быстрее примерно в 3 раза. Их скорости, кажется, скачкообразно скачут, и порядок не всегда соответствует. Я предполагаю, что это также может зависеть от размера процессора / памяти, но в целом я думаю, что буду придерживаться,bsxfun
когда это возможно.источник