Более быстрый способ инициализации массивов с помощью умножения пустых матриц? (Matlab)
Я наткнулся на странный путь (на мой взгляд), с которым Matlab имеет делопустые матрицы, Например, если умножить две пустые матрицы, результат будет:
zeros(3,0)*zeros(0,3)
ans =
0 0 0
0 0 0
0 0 0
Теперь, это уже застало меня врасплох, однако быстрый поиск привел меня к ссылке выше, и я получил объяснение несколько искаженной логики того, почему это происходит.
тем не мениеНичто не подготовило меня к следующему наблюдению. Я спросил себя, насколько эффективен этот тип умножения против простого использованияzeros(n)
Функция, скажем, с целью инициализации? Я использовалtimeit
чтобы ответить на это:
f=@() zeros(1000)
timeit(f)
ans =
0.0033
против:
g=@() zeros(1000,0)*zeros(0,1000)
timeit(g)
ans =
9.2048e-06
Оба имеют одинаковый результат 1000x1000 матрицы нулей классаdouble
, но умножение пустой матрицы 1 происходит в ~ 350 раз быстрее! (похожий результат происходит с использованиемtic
а такжеtoc
и петля)
Как это может быть? находятсяtimeit
или жеtic,toc
блеф или я нашел более быстрый способ инициализации матриц? (это было сделано с помощью matlab 2012a, на машине win7-64, intel-i5 650 3.2Ghz ...)
РЕДАКТИРОВАТЬ:
После прочтения вашего отзыва я более внимательно изучил эту особенность и протестировал на 2 разных компьютерах (один и тот же код версии 2012a) код, который проверяет время выполнения в зависимости от размера матрицы n. Вот что я получаю:
Код для создания этого используетсяtimeit
как и раньше, но петля сtic
а такжеtoc
будет выглядеть так же. Итак, для небольших размеров,zeros(n)
сопоставим. Тем не менее, вокругn=400
есть скачок в производительности для умножения пустой матрицы. Код, который я использовал для создания этого графика, был:
n=unique(round(logspace(0,4,200)));
for k=1:length(n)
f=@() zeros(n(k));
t1(k)=timeit(f);
g=@() 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)
кейс.