2015-02-25 2 views
21

Я пытаюсь найти самый быстрый способ стандартизации матрицы в Matlab (нулевые средние, столбцы дисперсии единиц). Все сводится к тому, что самый быстрый способ применения одной и той же операции ко всем строкам в матрице. Каждое сообщение, которое я прочитал, приходит к такому же выводу: использовать bsxfun вместо repmat. Эта статья, написанная Mathworks, является примером: http://blogs.mathworks.com/loren/2008/08/04/comparing-repmat-and-bsxfun-performance/Matlab - bsxfun не быстрее, чем repmat?

Однако при попытке этого на моем собственном компьютере repmat всегда быстрее. Вот мои результаты, используя один и тот же код, что и в статье:

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.0349 


ans = 

    0.0391 

На самом деле, я никогда не смогу получить bsxfun не лучше, чем repmat в этой ситуации независимо от того, насколько мала или большая входная матрица.

Может кто-нибудь объяснить это?

+1

Для меня подход bsxfun всегда быстрее, а также для больших массивов. (Matlab 2014a) – thewaywewalk

+0

Для меня (R2014b) выигрывает bsxfun. Какую версию Matlab вы используете? –

+0

Я пробовал это как на 2014a, так и на 2014b. Может ли использование ОС сделать разницу? Я на OSX. – user1337

ответ

11

Большинство советов, которые вы читаете, включая сообщение в блоге от Loren, скорее всего относится к старым версиям MATLAB, для которых bsxfun было довольно быстро, чем repmat. В R2013b (см. Раздел «Производительность» в ссылке) repmat был переопределен, чтобы обеспечить большие улучшения производительности при применении к числовым, символьным и логическим аргументам. В последних версиях он может быть примерно такой же скорости, как 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, если это возможно).


Edit: комментаторам попросили по определенной причине предпочитать 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 

(Adjust 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 действительно просто личное предпочтение, поскольку оно кажется немного более элегантным.

+1

'bsxfun' по-прежнему имеет преимущество использования меньшего объема памяти, поскольку он внутренне избегает повторения данных, правильно ли я? Я имею в виду, дайте повод для оправдания предпочтения 'bsxfun'! :-) –

+0

@ LuisMendo возможно ли повторная реализация 'repmat' избегает явной копии памяти? Возможно ли, что он реализует «ленивую» копию? У меня нет доступа к последним версиям Matlab ... – Shai

+0

@Shai Да, вот что я имел в виду с моим вопросом. Может быть, 'repmat' внутренне делает какую-то оптимизацию. Я не знаю. Но я все же предпочитаю 'bsxfun'! –