Получив несколько голосов за ответ, в котором используются вложенные вызовы permute
, я подумал о том, чтобы рассчитать время и сравнить его с другим ответом, в котором используется mat2cell
.
Это правда, что они не возвращают одно и то же, но:
- ячейка может быть легко преобразована в матрицу, как и другая (я засекал это, см. ниже);
- когда возникает эта проблема, предпочтительнее (по моему опыту) иметь данные в ячейке, так как позже часто захочется собрать оригинал обратно;
Во всяком случае, я сравнил их обоих со следующим сценарием. Код запускался в Octave (версия 3.9.1) с отключенным JIT.
function T = split_by_reshape_permute (A, m, n)
T = permute (reshape (permute (reshape (A, size (A, 1), n, []), [2 1 3]), n, m, []), [2 1 3]);
endfunction
function T = split_by_mat2cell (A, m, n)
l = size (A) ./ [m n];
T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1));
endfunction
function t = time_it (f, varargin)
t = cputime ();
for i = 1:100
f(varargin{:});
endfor
t = cputime () - t;
endfunction
Asizes = [30 50 80 100 300 500 800 1000 3000 5000 8000 10000];
Tsides = [2 5 10];
As = arrayfun (@rand, Asizes, "UniformOutput", false);
for d = Tsides
figure ();
t1 = t2 = [];
for A = As
A = A{1};
s = rows (A) /d;
t1(end+1) = time_it (@split_by_reshape_permute, A, s, s);
t2(end+1) = time_it (@split_by_mat2cell, A, s, s);
endfor
semilogy (Asizes, [t1(:) t2(:)]);
title (sprintf ("Splitting in %i", d));
legend ("reshape-permute", "mat2cell");
xlabel ("Length of matrix side (all squares)");
ylabel ("log (CPU time)");
endfor
Обратите внимание, что ось Y находится в логарифмическом масштабе.
![разделение 2D-матриц на 2](https://i.stack.imgur.com/U7OZO.jpg)
![разделение 2D-матриц на 10](https://i.stack.imgur.com/Q9VNx.jpg)
Представление
С точки зрения производительности использование вложенной перестановки будет быстрее только для меньших матриц, где большие изменения относительной производительности на самом деле являются очень небольшими изменениями во времени. Обратите внимание, что ось Y представлена в логарифмическом масштабе, поэтому разница между двумя функциями для матрицы 100 x 100 – 0,02 секунды, а для матрицы 10 000 x 10 000 – 100 секунд.
Я также протестировал следующее, которое преобразует ячейку в матрицу, чтобы возвращаемые значения двух функций были одинаковыми:
function T = split_by_mat2cell (A, m, n)
l = size (A) ./ [m n];
T = mat2cell (A, repmat (m, l(1), 1), repmat (n, l (2), 1), 1);
T = reshape (cell2mat (T(:)'), [m n numel(T)]);
endfunction
Это немного замедляет его, но не настолько, чтобы учитывать (линии будут пересекаться при разрешении 600 x 600 вместо 400 x 400).
Читабельность
Гораздо труднее понять, как использовать вложенную перестановку и изменение формы. Это безумие, чтобы использовать его. Это значительно увеличит время обслуживания (но эй, это язык Matlab, он не должен быть элегантным и пригодным для повторного использования).
Будущее
Вложенные вызовы permute вообще плохо расширяются в N измерений. Я предполагаю, что для этого потребуется цикл for по измерению (что совсем не поможет и без того довольно загадочному коду). С другой стороны, используя mat2cell:
function T = split_by_mat2cell (A, lengths)
dl = arrayfun (@(l, s) repmat (l, s, 1), lengths, size (A) ./ lengths, "UniformOutput", false);
T = mat2cell (A, dl{:});
endfunction
Изменить (и протестировать в Matlab)
Количество голосов за ответ, предлагающий использовать перестановку и изменение формы, вызвало у меня такое любопытство, что я решил протестировать это в Matlab (R2010b). Результаты там были почти такими же, т. Е. Производительность действительно плохая. Поэтому, если эта операция не будет выполняться много раз, в матрицах, которые всегда будут маленькими (менее 300x300), и всегда будет гуру Matlab, который объяснит, что она делает, не делайте этого. используй это.
person
carandraug
schedule
22.04.2015
30
, если вы собираетесь разбить матрицу на20x20
подматрицы - person Autonomous   schedule 02.12.2013mat2cell
подходит для разбиения матрицы на подматрицы. Ответ KlausCPH является хорошим примером. См. также здесь. - person chappjc   schedule 03.12.2013