Моя проблема заключается в том, чтобы быстро выполнить много низкоразмерных выступов в Matlab. У меня есть массив z
который имеет размеры (n,L,d)
; эти параметры получаются следующим образом. Я беру входной массив размера N, например N = [200, 200]
и n = prod(N) = 200*200 = 40,000
и d = numel(N) = 2
; т. е. n - количество точек в моей сетке дискретизации, а d - размер входного массива (например, изображение или плоскость из карты высоты). Затем я дискретирую возможные высоты (что моя программа будет выводить - обратите внимание на карту высоты выше) с L пунктами, скажем L = 32
.Быстрый алгоритм для нескольких проекций в Matlab
Для каждого i = 1:n
и j = 1:L
, я хочу, чтобы спроецировать вектор z(i,j,:)
на единичный шар * На данный момент у меня есть следующий наивный код:.
z = reshape(z,[n,L,d]); z_norms = norms(z,2,3);
for i = 1:n
for j = 1:L
z(i,j,:) = z(i,j,:)/max(1,z_norms(i,j));
end
end
Функция norms(v,p,dim)
принимает р норму матрицы v вдоль размерности dim (в этом случае выводится матрица (n,L)
).
У меня есть различные идеи относительно того, как это можно улучшить. Одна из идей заключалась в следующем:
for i = 1:n
for j = 1:L
normsquared = sum(z(i,j,:).^2)
if normsquared > 1
z(i,j,:) = z(i,j,:)/sqrt(normsquared)
end
end
end
Обратите внимание, что normsquared переписывается каждый раз, так что не занимая мое место. Когда я использовал это по другой проблеме, это ускорило процесс довольно много; однако я только что протестировал его по этой проблеме, и это на самом деле значительно хуже - примерно в три раза медленнее; на самом деле, требуется примерно в два с половиной раза вычислить normsquared
, как это делается для проекции в первом случае!
Странно, если я изменю sum(z(i,j,:).^2)
на z(i,j,1)^2 + z(i,j,2)^2
(в случае с d = 2), то это на самом деле немного быстрее, чем первый (наивный) метод ... если кто-то может объяснить это мне тоже, тогда это будь здорово!
Если у кого-то есть совет, как это ускорить, тогда я был бы очень благодарен! В настоящее время на это потрачено около 90% времени моей программы.
* На самом деле, я хочу, чтобы спроецировать его на лямбда раз единичный шар, где лямбда является еще одним параметром, но вряд ли это сделать разницу в алгоритме - просто разделить г на лямбда, сделать проекцию, а затем умножить на лямбда, например.
Спасибо. Да, это то, что я обычно делаю. Я предпочитаю писать код в наивном формате, прежде всего, только чтобы убедиться, что все это работает, а затем верните vectorize for-loops. Например, я имел «для j = 1: L, sum = sum + Gamma (j) * u (:, j), end", поэтому я изменил это на u * Gamma '(Gamma was (1, L)) , –
Можете ли вы объяснить немного больше, что делает функция «bsxfun»? Я видел, что раньше это использовалось для нескольких других вещей - я думаю, что это было векторизация умножения столбцов матрицы на вектор покомпонентно или что-то в этом роде. –
Кроме того, я думаю, вы имеете в виду «@rdivide», а не «@ldivide». Документация Matlab для 'bsxfun' наиболее неясна в этом вопросе, но я попробовал ее с' l', и это не сработало, но с 'r'. Как ни странно, использование 'bsxfun' не дает * точно * того же результата, что и использование циклов, только очень * похожего результата ... –