Эффективно переставляя вектор в 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 перестановок.

Другие вопросы по тегам