Время обработки Java Matrix

Мне нужно простое мнение от всех Гуру!

Я разработал программу для некоторых матричных вычислений. Работает все нормально с маленькой матрицей. Однако, когда я начинаю вычислять БОЛЬШУЮ матрицу строк столбца тысяч. Это убивает скорость.

Я думал обработать каждую строку и записать результат в файл, затем освободить память и начать обработку 2-й строки и записать в файл, и так далее.

Поможет ли это в увеличении скорости? Я должен внести большие изменения, чтобы реализовать это изменение. Вот почему мне нужно ваше мнение. Что вы думаете?

Спасибо

P.S: Я знаю про colt и Jama matrix. Я не могу использовать эти пакеты из-за правил компании.


Отредактировано

В моей программе я храню всю матрицу в двумерном массиве, и если матрица маленькая, все в порядке. Однако, когда он имеет тысячи столбцов и строк. Затем сохранение всей этой матрицы в памяти для расчета вызывает проблемы с производительностью. Матрица содержит плавающие значения. Для обработки я читаю всю матрицу, хранящуюся в памяти, затем начинаю расчет. После расчета записываю результат в файл.


person Tweet    schedule 27.08.2010    source источник
comment
В дополнение к тому, что сказали другие люди, вы можете описать здесь свой алгоритм и посмотреть, можно ли его улучшить. Скорее всего, сам алгоритм является узким местом.   -  person Nikita Rybak    schedule 28.08.2010
comment
Примите тот факт, что Java не предназначена для численного исчисления. Используйте другой инструмент, который будет соответствовать вашим потребностям.   -  person Andrei Ciobanu    schedule 28.08.2010


Ответы (4)


Действительно ли память является вашим узким местом? Потому что если это не так, то остановка записи в файл всегда будет намного, намного медленнее, чем альтернатива. Похоже, вы, вероятно, испытываете некоторые ограничения вашего алгоритма.

Возможно, вам следует сначала подумать об оптимизации алгоритма.

И, как я всегда говорю для всех вопросов производительности, спросить людей — это одно, но ничто не заменит попытки! Мнения не имеют значения, если реальная производительность измерима.

person Gian    schedule 27.08.2010
comment
можно сказать, что скорость обработки — мое узкое место. Я новичок в этой работе. Я не эксперт по Java+Math. Я не знаю, как понять, как то, что ест мою скорость. Я использовал jvisualvm, но он просто показывает высокоуровневый график, а не детали того, какая функция или класс потребляют мою скорость. - person Tweet; 29.08.2010

Я предлагаю использовать инструменты профилирования и временные операторы в вашем коде, чтобы точно определить, в чем проблема с производительностью, прежде чем вы начнете вносить изменения.

Вы можете потратить много времени на «исправление» того, что не является проблемой. Я подозреваю, что файловый ввод-вывод, который вы предлагаете, на самом деле замедлит ваш код.

Если ваш код фактически имеет цикл, вложенный в другой цикл для обработки каждого элемента, вы увидите, что ваша скорость быстро падает по мере увеличения размера матрицы. Если это так, областью, на которую следует обратить внимание, будет параллельная обработка ваших данных, позволяющая вашему коду использовать преимущества нескольких процессоров/ядер.

Рассмотрите более эффективную реализацию разреженной матричной структуры данных, а не многомерного массива (если вы используете его сейчас).

person brabster    schedule 27.08.2010
comment
Спасибо за ваш быстрый ответ. Я уже проверил, и это расчет матрицы, который вызывает проблемы с производительностью. В моей программе я храню всю матрицу в двумерном массиве, и если матрица маленькая, все в порядке. Однако, когда он имеет тысячи столбцов и строк. Затем сохранение всей этой матрицы в памяти для расчета вызывает проблемы с производительностью. Любая другая идея? - person Tweet; 28.08.2010
comment
Я не думаю, что вы можете сделать вывод, что проблема с производительностью связана с памятью. Допустим, у вас есть матрица двойников размером 5000x5000, а двойники используют 8 байт на вашей JVM. Хранение всей матрицы в памяти занимает 200 000 000 байт, или около 190 МБ - на современных компьютерах немного. Вы можете использовать такие инструменты, как jconsole, чтобы увидеть, какая память выделяется в вашей JVM и когда (что особенно важно) выполняется сборка мусора. - person brabster; 28.08.2010
comment
Вы пометили разреженные матрицы. Это означает, что многие элементы равны нулю. Если вы храните свои матрицы в виде двумерного массива и большинство элементов равны нулю, рассмотрите альтернативную реализацию, которая позволяет избежать хранения (и обработки) пустых элементов. Возможно, список непустых элементов, хранящих координаты каждого из них, сэкономит много памяти и позволит вам работать намного быстрее. - person brabster; 28.08.2010
comment
Спасибо за Ваш ответ:). Если вы собираетесь использовать несколько матриц 5000x5000 с другой матрицей 5000x5000, сколько памяти и процессора это будет потреблять? :) Я занимаюсь умножением, у меня 6 ГБ ОЗУ и core2du, и на его обработку уходят часы :( - person Tweet; 28.08.2010
comment
Является ли Java строгим требованием? Это звучит как то, что может быть хорошей идеей использовать специальную математическую программу (например, Mathematica). - person Thorbjørn Ravn Andersen; 28.08.2010

Вы должны помнить, что для выполнения NxN, умноженного на NxN, требуется 2xN^3 вычислений. Даже в этом случае это не должно занять несколько часов. Вы должны получить улучшение, транспонируя вторую матрицу (около 30%), но на самом деле это не должно занимать часы.

Таким образом, если вы удвоите N, вы увеличите время в 8 раз. Хуже того, матрица, которая помещается в ваш кеш, очень быстрая, но больше нескольких МБ, и они должны поступать из основной памяти, что замедляет ваши операции еще в 2-5 раз.

Помещение данных на диск действительно замедлит ваши вычисления, я предлагаю вам сделать это только в том случае, если ваш martix не помещается в памяти, но это сделает его в 10-100 раз медленнее, поэтому покупка немного больше памяти - хорошая идея. (В вашем случае ваши матрицы должны быть достаточно маленькими, чтобы поместиться в память)

Я попробовал Jama, очень простую библиотеку, которая использует двумерные массивы вместо одного, и на 4-летнем компьютере это заняло 7 минут. Вы должны быть в состоянии получить половину этого времени, просто используя новейшее оборудование и несколько потоков, сократив это время до одной минуты.

EDIT: Используя Xeon X5570, Джама умножил две матрицы 5000x5000 за 156 секунд. Используя параллельную реализацию, которую я написал, сократите это время до 27 секунд.

person Peter Lawrey    schedule 28.08.2010
comment
Привет, Питер! Большое спасибо. Просто для собственного эксперимента. Я также скачал jama и использовал матрицу 7000X4000, просто чтобы выполнить расчет SVD на моей машине. Это заняло несколько минут и выдало ошибку размера кучи. Я просто использую их пример с моей матрицей. Если хотите, я могу предоставить вам пример, но я думаю, что вы также можете скачать его с помощью jama. Так в чем проблема? Я использовал jvisualvm, чтобы увидеть, где я ошибаюсь. Это снова показало мне, что размер кучи увеличивается и уменьшается, но не место или класс, где я ошибаюсь. Как я могу увидеть, какой класс, функция или оператор потребляют мою скорость? - person Tweet; 29.08.2010
comment
Запустив Matrix.random(7000,4000).svd(), использование памяти началось с 812 МБ и осталось на этом уровне. Jama SVD создает три рабочие области примерно такого же размера, как ваш исходный массив. Я предлагаю вам выделить JVM не менее 1 ГБ. то есть -mx1g в командной строке. - person Peter Lawrey; 31.08.2010
comment
Профилировщики обычно имеют инструменты на уровне методов, т.е. они сообщают вам, сколько времени потрачено на один метод. Однако, поскольку все работает в одном методе, вам нужно будет добавить свои собственные инструменты/тайминги, используя System.nanoTime(). Это работает для значительного блока работы, однако, если вы ищете, какое выражение или доступ к массиву занимает больше всего времени, вам придется попробовать удалить его и посмотреть, как это повлияет на время. например заменить доступ к массиву локальной переменной. - person Peter Lawrey; 31.08.2010

Используйте профилировщик в jvisualvm в JDK, чтобы определить, где тратится время.

Я бы провел несколько простых экспериментов, чтобы определить, как масштабируется ваш алгоритм, потому что похоже, что вы можете использовать тот, который имеет более высокую сложность выполнения, чем вы думаете. Если он работает в N ^ 3 (что обычно, если вы хотите умножить список на массив), то удвоение размера ввода увеличит время выполнения в восемь раз.

person Thorbjørn Ravn Andersen    schedule 28.08.2010
comment
Спасибо за Ваш ответ. Как я могу увидеть, какой класс, функция или оператор потребляют мою скорость в jvisualvm? - person Tweet; 29.08.2010