Эффективно переставляя вектор в Matlab
Я хочу сделать 1000 случайных перестановок вектора в Matlab. Я делаю это так
% vector is A
num_A = length(A);
for i=1:1000
n = randperm(num_A);
A = A(n); % This is one permutation
end
Это займет около 73 секунд. Есть ли способ сделать это более эффективно?
2 ответа
Проблема 1 - Перезапись исходного вектора внутри цикла
Каждый раз A = A(n);
перезапишу A
входной вектор с новой перестановкой. Это может быть разумно, так как в любом случае вам не нужен порядок, но все элементы в A
, Однако это крайне неэффективно, потому что вы должны переписывать массив из миллиона элементов в каждой итерации.
Решение: сохранить перестановку в новой переменной -
B(ii, :) = A(n);
Проблема 2 - Использование i
как итератор
Мы в Stackru всегда говорим серьезным пользователям Matlab, что i
а также j
так как интеграторы в циклах это абсолютно плохая идея. Проверьте этот ответ, чтобы понять, почему он замедляет ваш код, и посмотрите другие ответы на этой странице, чтобы узнать, почему это плохо
Решение - использовать ii
вместо i
,
Проблема 3 - Использование ненужного for
петля
На самом деле вы можете избежать этого for
цикл вообще, поскольку итерации не связаны друг с другом, и это будет быстрее, если вы разрешите Matlab выполнять параллельные вычисления.
Решение - использовать arrayfun
генерировать 1000 результатов одновременно.
Окончательное решение
использование arrayfun
чтобы генерировать 1000 x num_A
индексы. Я думаю (не подтвердил), что это быстрее, чем прямой доступ A
,
n = cell2mat(arrayfun(@(x) randperm(num_A), 1:1000', 'UniformOutput', false)');
Затем сохраните все 1000 перестановок одновременно в новую переменную.
B = A(n);
Я нашел этот код довольно привлекательным. Вы можете заменить randperm
с Shuffle
, Пример кода -
B = Shuffle(repmat(A, 1000, 1), 2);
A = perms(num_A)
A = A(1:1000)
Perms возвращает все различные перестановки, просто возьмите первые 1000 перестановок.