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



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

есть ли у людей опыт работы с библиотеками Java для matrix math (например, multiply, inverse и т. д.)? Например:

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


детали нашего сравнения скорости:

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

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

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

260   19  

19 ответов:

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

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

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

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

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

поэтому для меня было ясно, что библиотеки Java не слишком хорошо. Однако если кто-то должен кодировать на Java, то лучшим вариантом является JBLAS. Джама, Кольт и параллельный Кольт не быстры.

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

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

Если вы работаете с" большими " матрицами и можете использовать собственные библиотеки, то явный победитель (о 3.5 x быстрее) составляет MTJ С система оптимизирована netlib. Если вам нужно чистое решение на Java, то MTJ,OjAlgo,EJML и Параллельные Кольт - это хороший выбор. Для малых матриц ejml является явным победителем.

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

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

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

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

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

импорт статических джейген.Матриксутил.*;

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 есть синтаксис terser, т. е. "mmul" против "multiplyRight"

Я только что сравнил Apache Commons Math с jlapack.

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

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

Октавный код: A=rand (1024); tic; [U,S,V]=svd(A); 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. Я использовал двоичную библиотеку lapack, поставляемую с дистрибутивом linux, и вызвал в dgesvd рутины, чтобы получить у S и матрицы Вт, а также. Все тесты были выполнены с использованием двойной точности на точно такой же матрице каждый прогон (кроме Октавы).

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

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

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

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

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

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

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

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

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

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

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

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

вы взглянули на Библиотека Ядра Intel Math? Он утверждает, что превосходит даже атлас. МКЛ может быть используется в Java через обертки JNI.

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

основываясь на сообщении Вархана, что собственный код Pentium будет лучше:

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

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

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

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

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

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

там же UJMP

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

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

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

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

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

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

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

    Ничего не найдено.

Добавить ответ:
Отменить.