Я наткнулся на странный способ (на мой взгляд), что Matlab имеет дело с пустыми матрицами. Например, если две пустые матрицы умножаются, результат:
zeros(3,0)*zeros(0,3)
ans =
0 0 0
0 0 0
0 0 0
Теперь это уже застало меня врасплох, однако быстрый поиск привлек меня к ссылке выше, и я получил объяснение несколько искаженной логики, почему это происходит.
Однако, ничто не подготовило меня к следующему наблюдению. Я спросил себя: насколько эффективен этот тип умножения и просто используется функция zeros(n)
, например, для инициализации? Я использовал timeit
, чтобы ответить на это:
[email protected]() zeros(1000)
timeit(f)
ans =
0.0033
против
[email protected]() zeros(1000,0)*zeros(0,1000)
timeit(g)
ans =
9.2048e-06
Оба имеют одинаковый результат матрицы 1000x1000 нулей класса double
, но пустая матрица умножается на ~ 350 раз быстрее! (аналогичный результат происходит с использованием tic
и toc
и цикла)
Как это может быть? timeit
или tic,toc
блеф или я нашел более быстрый способ инициализации матриц?
(это было сделано с помощью matlab 2012a, на машине win7-64, intel-i5 650 3.2Ghz...)
EDIT:
После прочтения ваших отзывов я более тщательно рассмотрел эту особенность и протестировал на двух разных компьютерах (тот же самый matlab ver, хотя 2012a) код, который проверяет время выполнения и размер матрицы n. Это то, что я получаю:
Код для генерации этого используемого timeit
, как и раньше, но цикл с tic
и toc
будет выглядеть одинаково. Таким образом, для небольших размеров zeros(n)
сравнимо. Однако вокруг n=400
наблюдается скачок производительности для пустого матричного умножения. Код, который я использовал для создания этого сюжета, был:
n=unique(round(logspace(0,4,200)));
for k=1:length(n)
[email protected]() zeros(n(k));
t1(k)=timeit(f);
[email protected]() zeros(n(k),0)*zeros(0,n(k));
t2(k)=timeit(g);
end
loglog(n,t1,'b',n,t2,'r');
legend('zeros(n)','zeros(n,0)*zeros(0,n)',2);
xlabel('matrix size (n)'); ylabel('time [sec]');
Вы тоже испытываете это?
РЕДАКТИРОВАТЬ № 2:
Кстати, пустое матричное умножение не требуется для получения этого эффекта. Можно просто сделать:
z(n,n)=0;
где n > некоторый пороговый размер матрицы, рассматриваемый на предыдущем графике, и получить профиль эффективности точный, как с пустым умножением матрицы (снова используя timeit).
Здесь пример, где он повышает эффективность кода:
n = 1e4;
clear z1
tic
z1 = zeros( n );
for cc = 1 : n
z1(:,cc)=cc;
end
toc % Elapsed time is 0.445780 seconds.
%%
clear z0
tic
z0 = zeros(n,0)*zeros(0,n);
for cc = 1 : n
z0(:,cc)=cc;
end
toc % Elapsed time is 0.297953 seconds.
Однако использование z(n,n)=0;
приводит к аналогичным результатам в случае zeros(n)
.