Производительность математических математических библиотек Java?

Мы вычисляем что-то, чье исполнение связано с матричными операциями. (Некоторые подробности ниже, если они заинтересованы.) Этот опыт вызвал следующий вопрос:

Есть ли у людей опыт работы с библиотеками Java для математической математики (например, умножить, инвертировать и т.д.)? Например:

Я искал и ничего не нашел.


Подробная информация о нашем сравнении скорости:

Мы используем Intel FORTRAN (IFORT) 10.1 20070913). Мы переопределили его на Java (1.6), используя матричные операционные системы Apache commons math 1.2, и он согласен со всеми его цифрами точности. (У нас есть причины для этого в Java.) (Java удваивает, Fortran real * 8). Fortran: 6 минут, Java 33 минуты, одна и та же машина. Профайлинг jvisualm показывает много времени, проведенного в RealMatrixImpl. {getEntry, isValidCoordinate} (которые, кажется, ушли в неизданный Apache commons math 2.0, но 2.0 не быстрее). Fortran использует процедуры Atlas BLAS (dpotrf и т.д.).

Очевидно, это может зависеть от нашего кода на каждом языке, но мы верим, что большая часть времени находится в эквивалентных матричных операциях.

В нескольких других вычислениях, которые не связаны с библиотеками, Java не была намного медленнее, а иногда и намного быстрее.

Ответ 1

Просто добавьте свои 2 цента. Я сравнил некоторые из этих библиотек. Я попытался матрицей умножить 3000 на 3000 матриц двойников с собой. Результаты следующие.

Используя многопоточность ATLAS с C/С++, Octave, Python и R, время было около 4 секунд.

Используя Jama с Java, время было 50 секунд.

Используя Colt и Parallel Colt с Java, время было 150 секунд!

Используя JBLAS с Java, время было снова около 4 секунд, поскольку JBLAS использует многопоточную ATLAS.

Итак, для меня стало ясно, что библиотеки Java не слишком хорошо работают. Однако, если кто-то должен закодировать на Java, лучшим вариантом является JBLAS. Jama, Colt и Parallel Colt не быстры.

Ответ 2

Я являюсь автором Java Matrix Benchmark (JMatBench), и я расскажу об этом обсуждении.

Существует значительная разница между библиотеками Java, и пока нет четкого победителя во всем диапазоне операций, есть несколько явных лидеров, которые можно увидеть в последних результатах производительности (октябрь 2013 г.).

Если вы работаете с "большими" матрицами и можете использовать собственные библиотеки, то явный победитель (примерно в 3,5 раза быстрее) MTJ с оптимизированная система netlib. Если вам нужно чистое решение Java, MTJ, OjAlgo, EJML и Parallel Colt - хороший выбор. Для маленьких матриц EJML является явным победителем.

Библиотеки, о которых я не упоминал, показали значительные проблемы с производительностью или отсутствовали ключевые функции.

Ответ 3

Я главный автор jblas и хотел указать, что я выпустил версию 1.0 в конце декабря 2009 года. Я много работал над упаковкой, а это значит, что теперь вы можете просто загрузить "толстую банку" с ATLAS и библиотеки JNI для Windows, Linux, Mac OS X, 32 и 64 бит (за исключением Windows). Таким образом, вы получите прирост производительности, просто добавив файл jar в свой путь к классам. Проверьте это на http://jblas.org!

Ответ 4

Я просто сравнил Apache Commons Math с jlapack.

Тест: разложение по сингулярным значениям случайной матрицы 1024x1024.

Машина: Intel (R) Core (TM) 2 Duo CPU E6750 @2.66GHz, linux x64

Октавный код: A = rand (1024); крестики; [U, S, V] = SVD (А); TOC

results                                execution time
---------------------------------------------------------
Octave                                 36.34 sec

JDK 1.7u2 64bit
    jlapack dgesvd                     37.78 sec
    apache commons math SVD            42.24 sec


JDK 1.6u30 64bit
    jlapack dgesvd                     48.68 sec
    apache commons math SVD            50.59 sec

Native routines
Lapack* invoked from C:                37.64 sec
Intel MKL                               6.89 sec(!)

Мой вывод состоит в том, что jlapack, вызванный из JDK 1.7, очень близок к родному двоичная производительность лапака. Я использовал библиотеку lapack binary, поставляемую с дистрибутивом linux, и вызвал процедуру dgesvd, чтобы получить матрицы U, S и VT. Все тесты проводились с использованием двойной точности на одной и той же матрице каждого прогона (кроме Octave).

Отказ от ответственности - я не эксперт в линейной алгебре, не связан с какой-либо из вышеперечисленных библиотек, и это не является строгим эталоном. Это был "домашний" тест, так как мне было интересно сравнить увеличение производительности JDK 1.7 до 1.6, а также обычную математику SVD для jlapack.

Ответ 5

Jeigen https://github.com/hughperkins/jeigen

  • обертывает библиотеку Eigen С++ http://eigen.tuxfamily.org, которая является одной из самых быстрых бесплатных библиотек С++.
  • относительно краткий синтаксис, например 'mmul', 'sub'
  • обрабатывает как плотные, так и разреженные матрицы

Быстрый тест путем умножения двух плотных матриц, т.е.

import static jeigen.MatrixUtil. *;

int K = 100;
int N = 100000;
DenseMatrix A = rand(N, K);
DenseMatrix B = rand(K, N);
Timer timer = new Timer();
DenseMatrix C = B.mmul(A);
timer.printTimeCheckMilliseconds();

Результаты:

Jama: 4090 ms
Jblas: 1594 ms
Ojalgo: 2381 ms (using two threads)
Jeigen: 2514 ms
  • По сравнению с jama все быстрее: -P
  • По сравнению с jblas, Jeigen не так быстро, но он обрабатывает разреженные матрицы.
  • По сравнению с ojalgo, Jeigen занимает примерно такое же количество прошедшего времени, но только с использованием одного ядра, поэтому Jeigen использует половину всего процессора. Jeigen имеет синтаксис терминов, т.е. 'Mmul' в сравнении с 'multiplyRight'

Ответ 6

Я не могу прокомментировать конкретные библиотеки, но в принципе у меня мало причин, чтобы такие операции были медленнее в Java. Hotspot обычно выполняет те вещи, которые вы ожидаете от компилятора: он компилирует основные математические операции с переменными Java в соответствующие машинные инструкции (он использует инструкции SSE, но только один для каждой операции); доступ к элементам массива скомпилирован для использования "необработанных" инструкций MOV, как вы ожидали; он принимает решения о том, как распределять переменные в регистры, когда это возможно; он переупорядочивает инструкции, чтобы воспользоваться архитектурой процессора... Возможно, исключение состоит в том, что, как я уже упоминал, Hotspot будет выполнять только одну операцию в команде SSE; в принципе вы могли бы получить фантастически оптимизированную библиотеку матриц, которая выполняла несколько операций для каждой инструкции, хотя я не знаю, может ли ваша конкретная библиотека FORTRAN делать это или существует ли такая библиотека. Если это так, в настоящее время нет возможности для Java (или, по крайней мере, Hotspot) конкурировать с этим (хотя вы, конечно, можете написать свою собственную родную библиотеку с этими оптимизациями для вызова с Java).

Итак, что все это значит? Ну:

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

Вмешательство в операции с матрицами часто связано с проблемами локальности данных, которые возникают, когда вам нужно перемещаться как по строке, так и по столбцу по столбцу, например. в матричном умножении, так как вы должны хранить данные в порядке, который оптимизирует тот или иной. Но если вы вручную пишете код, иногда вы можете комбинировать операции для оптимизации локализации данных (например, если вы умножаете матрицу на ее преобразование, вы можете повернуть обход столбца в обход строки, если вы написать специальную функцию вместо объединения двух функций библиотеки). Как обычно в жизни, библиотека даст вам неоптимальную производительность в обмен на более быстрое развитие; вам нужно решить, насколько важна ваша производительность.

Ответ 7

Там есть таблица различных пакетов матриц, доступных в java up on http://code.google.com/p/java-matrix-benchmark/ для нескольких различных конфигураций оборудования. Но это не замена для собственного теста.

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

Как правило, JAMA, Jampack и COLT стареют и не представляют состояние текущей производительности, доступное в Java для линейной алгебры. Более современные библиотеки более эффективно используют несколько ядер и процессоров cpu. JAMA была эталонной реализацией, и в значительной степени реализует алгоритмы учебников с небольшим учетом производительности. COLT и IBM Ninja были первыми java-библиотеками, которые показали, что производительность возможна в Java, даже если они отстают от родных библиотек на 50%.

Ответ 8

Я являюсь автором la4j (Linear Algebra for Java), и вот моя точка. Я работаю над la4j в течение 3 лет (последняя версия - 0.4.0 [01 июня 2013]), и только теперь я могу начать делать анализ и оптимизацию, так как я только что рассмотрел минимально необходимый функционал. Итак, la4j не так быстро, как я хотел, но я трачу массу времени, чтобы изменить его.

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

Ответ 10

Мы использовали COLT для некоторых довольно крупных серьезных финансовых расчетов и были очень довольны этим. В нашем сильно профилированном коде нам почти никогда не приходилось заменять реализацию COLT одним из наших.

В своем собственном тестировании (очевидно, не независимом), я думаю, что они заявляют в 2 раза из русифицированных вручную ассемблерных подпрограмм Intel. Трюк для его использования - это то, что вы понимаете их философию дизайна и избегаете постороннего выделения объектов.

Ответ 11

Код Linalg, который в значительной степени зависит от возможностей векторных вычислений Pentium и более поздних процессоров (начиная с расширений MMX, таких как LAPACK, а теперь и Atlas BLAS), не "фантастически оптимизирован", а просто отраслевым стандартом. Чтобы воспроизвести это исполнение на Java, вам понадобятся родные библиотеки. У меня была такая же проблема с производительностью, как вы описываете (в основном, чтобы вычислить разложения Choleski) и не нашли ничего действительно эффективного: Jama - это чистая Java, поскольку она должна быть просто шаблоном и эталонным набором для исполнителей... которого никогда не было. Вы знаете математическое сообщество Apache... Что касается COLT, я все еще должен его протестировать, но, похоже, он сильно зависит от улучшений ниндзя, большинство из которых были достигнуты путем создания специального Java-компилятора, поэтому я сомневаюсь, что это поможет. В этот момент я думаю, что мы "просто" нуждаемся в коллективных усилиях по созданию собственной реализации Jama...

Ответ 13

Вы можете проверить проект jblas. Это относительно новая библиотека Java, которая использует BLAS, LAPACK и ATLAS для высокопроизводительных матричных операций.

Разработчик опубликовал некоторые тесты, в которых jblas выгодно отличается от MTJ и Colt.

Ответ 14

Для приложений с 3D-графикой реализация вектора lwjgl.util выполняется выше упомянутых jblas в 3 раза.

Я сделал 1 миллион матричных умножений vec4 с матрицей 4x4.

lwjgl закончил около 18 мс, jblas потребовалось около 60 мс.

(я предполагаю, что подход JNI не очень подходит для быстрого последовательного применения относительно небольших умножений. Поскольку перевод/отображение может занимать больше времени, чем фактическое выполнение умножения.)

Ответ 15

Там также UJMP

Ответ 16

Существует множество различных свободно доступных библиотек линейной алгебры Java. http://www.ujmp.org/java-matrix/benchmark/ К сожалению, этот тест дает вам информацию о матричном умножении (с транспонированием теста не позволяет различным библиотекам использовать их соответствующие конструктивные элементы).

Что вы должны посмотреть, так это то, как эти библиотеки линейной алгебры выполняют, когда их просят вычислить различные разложения матриц. http://ojalgo.org/matrix_compare.html

Ответ 17

Я обнаружил, что если вы создаете много многомерных матриц, вы можете сделать Jama примерно на 20% быстрее, если вы измените его на использование одномерного массива вместо двухмерного массива. Это связано с тем, что Java не поддерживает многомерные массивы так же эффективно. то есть. он создает массив массивов.

Colt делает это уже, но я обнаружил, что он более сложный и мощный, чем Jama, который может объяснить, почему простые функции медленнее с Colt.

Ответ действительно зависит от того, что вы делаете. Jama не поддерживает часть вещей, которые может сделать Colt, которые делают большую разницу.

Ответ 18

Matrix Tookits Java (MTJ) уже упоминался ранее, но, возможно, стоит упомянуть еще раз о том, что кто-то еще споткнулся об этой теме. Для тех, кто заинтересован, кажется, что там также говорят о том, что MTJ заменяет библиотеку linalg в apache commons math 2.0, хотя я не уверен как это происходит в последнее время.

Ответ 19

Вы должны добавить Apache Mahout в свой список покупок.

Ответ 20

Вы не случайно попали в версию Java? Тот факт, что вы проводите большую часть своего времени в getEntry(), является ключом к тому, что это происходит.

Другая проблема, которую я вижу в Commons-Math, заключается в том, что матрица управляется как двумерный массив. Хотя я не ожидаю, что причиной двойного разрыва является причина замедления, это означает, что отдельные строки (при условии [rowIdx] [colIdx]) являются фактически отдельными объектами, которые будут обрабатываться отдельно GC. Вы проводите много времени в GC?