Отладка: необычное время выполнения в вычислениях линейной алгебры с использованием Java, ojalgo
У меня умеренно большой Ax = b
проблема, которую я хочу решить. Матрица А есть 600x600
,
Мой код решает проблему, но занимает необычно много времени. Итак, я попытался проверить (с System.currentTimeMillis()
), чтобы увидеть, где мой код замедляется.
Оказывается, что во время расчетов А я выполняю команду A = L1 * A0 * L1.transpose()
, Процесс занимает почти 100% своего общего времени в этой линии.
Странная вещь, L1 является 600x600
единичная матрица (то есть A[i,j] = 1
, если i == j
а также 0
, иначе). Таким образом, эта строка не должна занимать так много времени для выполнения. Также должно быть легко обойти эту проблему
Даже более странная вещь произойдет, если я попытаюсь обойти эту строку, закомментировав ее и заменив ее A = A0
, Затем выполнение кода занимает слишком много времени (после 10-кратного первоначального времени, когда я его убил). Также загрузка процессора достигает 100%.
Я проверил, и получается, что A
а также L1 * A0 * L1.transpose()
идентичны
Подводя итог, используя часть моего Java-кода (я использую библиотеку ojalgo для обработки матриц):
// PrimitiveMatrix A0, L1, b are already calculated.
long startTime = System.currentTimeMillis();
System.out.println((System.currentTimeMillis() - startTime0) / 1000.0); // this prints about 2 seconds, concerning calculations of A0, L1, b.
PrimitiveMatrix A = L1.multiply(A0).multiply((L1).transpose());
System.out.println((System.currentTimeMillis() - startTime0) / 1000.0); // this prints about 67 seconds
// PrimitiveMatrix A = A0; // if this is NOT a comment, then the code has not run after (10+)x my "normal" time
final PrimitiveMatrix x = (A.invert()).multiply(b);
System.out.println((System.currentTimeMillis() - startTime0) / 1000.0); // this prints about 69 seconds
// I checked that
// A0.equals(L1.multiply(A0).multiply((L1).transpose())
// returns true
Весь этот процесс занимает около 69 секунд, и 65 из них потребляются в тривиальном расчете, который я не смог обойти. Та же самая процедура успешно выполнялась в прошлом для меньших матриц (60x60).
Я не совсем уверен, как продолжить мои попытки отладки. Любая помощь будет принята с благодарностью.
Кажется, проблема немного глубже, чем я предполагал. Я попытался распечатать эти матрицы, чтобы загрузить их, но затем появилась другая проблема. Я обнаружил, что мой код падает при первом запуске System.out.println(A0.get(aRow,aColumn));
, A0
был создан путем добавления чисел типа double к каждой позиции нулевой матрицы с размерами 600x600
, Кроме того, появляются следующие сообщения:
Exception in thread "main" java.lang.StackruError
at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
at org.ojalgo.matrix.store.SuperimposedStore.get(SuperimposedStore.java:84)
...
Опять же, я хочу подчеркнуть, что тот же процесс работает нормально, когда эти матрицы 60x60
,
1 ответ
Я предполагаю, что вы используете BasicMatrix#add(int,int,Number)
Вы вызывали этот метод 600x600 раз, чтобы построить свою матрицу? Вы не должны этого делать!
В более новых версиях ojAlgo этот метод был удален, потому что его часто неправильно понимали / неправильно использовали.
Вы должны прочитать это: https://github.com/optimatika/ojAlgo/wiki/Getting-Started