У меня есть функция в MATLAB, которая выполняет Gram-Schmidt Orthogonalisation с очень важным весом, применяемым к внутренним продуктам (я не знаю Не думаю, что встроенная функция MATLAB поддерживает это). Эта функция работает хорошо, насколько я могу судить, однако она слишком медленная на больших матрицах. Какой был бы лучший способ улучшить это?
Я пробовал конвертировать в MEX файл, но я теряю параллелизацию с используемым компилятором, и поэтому он медленнее.
Я думал запустить его на графическом процессоре, поскольку умножения по элементам сильно распараллеливаются. (Но я бы предпочел, чтобы реализация была легко переносимой)
Может ли кто-нибудь прорисовать этот код или сделать его быстрее? Я не уверен, как это сделать элегантно...
Я знаю, что улов stackoverflow здесь потрясающий, рассмотрите эту задачу:)
Функция
function [Q, R] = Gram_Schmidt(A, w)
[m, n] = size(A);
Q = complex(zeros(m, n));
R = complex(zeros(n, n));
v = zeros(n, 1);
for j = 1:n
v = A(:,j);
for i = 1:j-1
R(i,j) = sum( v .* conj( Q(:,i) ) .* w ) / ...
sum( Q(:,i) .* conj( Q(:,i) ) .* w );
v = v - R(i,j) * Q(:,i);
end
R(j,j) = norm(v);
Q(:,j) = v / R(j,j);
end
end
где A
- матрица m x n
комплексных чисел, а w
- вектор вещественных чисел m x 1
.
Бутылка шея
Это выражение для R(i,j)
, которое является самой медленной частью функции (не на 100% уверенно, если нотация правильная):
где w
- неотрицательная весовая функция.
Весовой внутренний продукт упоминается на нескольких страницах Википедии, это один из весовых функций и это одно из ортогональных функций.
Воспроизведение
Вы можете создавать результаты, используя следующий script:
A = complex( rand(360000,100), rand(360000,100));
w = rand(360000, 1);
[Q, R] = Gram_Schmidt(A, w);
где A
и w
- входы.
Скорость и вычисления
Если вы используете вышеуказанный script, вы получите результаты профилировщика, синонимичные следующим образом:
Результат тестирования
Вы можете проверить результаты, сравнив функцию с приведенной выше, используя следующий script:
A = complex( rand( 100, 10), rand( 100, 10));
w = rand( 100, 1);
[Q , R ] = Gram_Schmidt( A, w);
[Q2, R2] = Gram_Schmidt2( A, w);
zeros1 = norm( Q - Q2 );
zeros2 = norm( R - R2 );
где Gram_Schmidt
- функция, описанная ранее, и Gram_Schmidt2
- альтернативная функция. Результаты zeros1
и zeros2
должны быть очень близки к нулю.
Примечание:
Я попытался ускорить вычисление R(i,j)
следующим, но безрезультатно...
R(i,j) = ( w' * ( v .* conj( Q(:,i) ) ) ) / ...
( w' * ( Q(:,i) .* conj( Q(:,i) ) ) );