Ответ 1
Большинство советов, которые вы читаете, включая сообщение в блоге от Loren, скорее всего, относятся к старым версиям MATLAB, для которых bsxfun
было довольно быстро, чем repmat
. В R2013b (см. Раздел "Производительность" в ссылке), repmat
был переопределен, чтобы обеспечить большие улучшения производительности при применении к числовым, char и логические аргументы. В последних версиях он может быть примерно такой же скорости, как bsxfun
.
Для чего это стоит, на моей машине с R2014a я получаю
m = 1e5;
n = 100;
A = rand(m,n);
frepmat = @() A - repmat(mean(A),size(A,1),1);
timeit(frepmat)
fbsxfun = @() bsxfun(@minus,A,mean(A));
timeit(fbsxfun)
ans =
0.03756
ans =
0.034831
похоже, что bsxfun
по-прежнему крошечный бит быстрее, но не так много - и на вашей машине, похоже, наоборот. Конечно, эти результаты, скорее всего, будут меняться снова, если вы измените размер A
или операцию, которую вы применяете.
По-прежнему могут быть другие причины предпочесть одно решение над другим, например, элегантность (я предпочитаю bsxfun
, если это возможно).
Изменить: комментаторы задали определенную причину, чтобы предпочесть bsxfun
, подразумевая, что она может использовать меньше памяти, чем repmat
, избегая временного копирования, которое repmat
не поддерживает.
Я не думаю, что это на самом деле. Например, откройте диспетчер задач (или эквивалент на Linux/Mac), посмотрите уровни памяти и введите:
>> m = 1e5; n = 8e3; A = rand(m,n);
>> B = A - repmat(mean(A),size(A,1),1);
>> clear B
>> C = bsxfun(@minus,A,mean(A));
>> clear C
(Настройте m
и n
, пока прыжки не будут видны на графике, но не настолько велики, что у вас не хватает памяти).
Я вижу точно такое же поведение как от repmat
, так и от bsxfun
, что означает, что память плавно переходит на новый уровень (в основном удваивает размер A
) без временного дополнительного пика.
Это также происходит, даже если операция выполняется на месте. Опять же, посмотрите память и введите:
>> m = 1e5; n = 8e3; A = rand(m,n);
>> A = A - repmat(mean(A),size(A,1),1);
>> clear all
>> m = 1e5; n = 8e3; A = rand(m,n);
>> A = bsxfun(@minus,A,mean(A));
Опять же, я вижу точно такое же поведение как с repmat
, так и bsxfun
, то есть память поднимается до пика (в основном вдвое больше размера A
), а затем возвращается к предыдущему уровню.
Так что, боюсь, я не вижу много технических различий с точки зрения скорости или памяти между repmat
и bsxfun
. Мое предпочтение bsxfun
действительно является личным предпочтением, поскольку оно выглядит немного более элегантным.