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


151

Ми обчислюємо щось, час виконання якого пов'язаний матричними операціями. (Деякі деталі нижче, якщо вас цікавить.) Цей досвід викликав наступне питання:

Чи має народ у досвіді роботи бібліотек Java для математики матриці (наприклад, множення, обернення тощо)? Наприклад:

Я шукав і нічого не знаходив.


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

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

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

У кількох інших обчисленнях, які не включають бібліотеки, Java не була набагато повільнішою, а іноді і значно швидшою.


Хитра матриця з математики є як мінімум O (n ^ 3) ... гірше прийде до гіршого, я думаю, ви могли б вчасно і перевірити ...
Calyth

2
Для чого потрібні інверси? Практично для всіх застосувань вам не потрібен власне обернений. Обчислення зворотного - погана ідея через проблеми зі стабільністю.
Ін Сяо

1
@Calyth: Так, ми можемо встигнути. Мені було цікаво, чи були інші. @Ying Xiao: Так, слід уникати зворотних зв'язків. Однак це обчислення видається найпростішим за його використання. Дивіться en.wikipedia.org/wiki/… .
dfrankow

2
@Calyth Це неправильно, існують більш ефективні методи, ніж O (n ^ 3), використовуючи підхід ділити і перемогти.
starblue

1
Найшвидший рідний виступ від JCublas. Якщо вам потрібна швидка лінійна алгебра, вам потрібні графічні процесори. JOCL з clMath також може працювати і бути переносним для процесорів (і навіть багатоплатформних без перекомпіляції), але я не перевіряв його.
Олександр Дубінський

Відповіді:


98

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

Використовуючи багатопотокові ATLAS з C / C ++, Octave, Python та R, час займав близько 4 секунд.

Використовуючи Джаму з Java, час займав 50 секунд.

Використовуючи Кольт і Паралельний Кольт з Java, час займав 150 секунд!

Використовуючи JBLAS з Java, час зайнято знову близько 4 секунд, оскільки JBLAS використовує багатопотокові ATLAS.

Тож для мене було зрозуміло, що бібліотеки Java працюють не надто добре. Однак якщо комусь доводиться кодувати на Java, то найкращий варіант - JBLAS. Джама, Кольт і Паралельний Кольт не швидкі.


3
Я думаю, ви використовували багатоядерну машину, тому на ці результати сильно впливає, використовує чи багато бібліотека багатоядерна чи ні? Для деяких цілей, наприклад , коли один розпаралелювання з використанням МПІ або Hadoop і т.д., важливий час насправді singlecore час, так як реалізація MPI / Hadoop піклується про розпаралелювання речі. (Принаймні, для мене jblas був приблизно на 2,5 швидше, ніж джама, не в 10 разів швидше, ніж джама.)
Х'ю Перкінс

17
Щойно я випустив версію netlib-java v1.0 ... продуктивність знаходиться нарівні (а іноді і перевершує) код Fortran, і він може використовувати машинні оптимізовані вихідці без будь-яких змін у коді користувача. Зверніть увагу на це, шукаючи низькорівневі бібліотеки лінійних алгебр. Я також підтримую MTJ , який використовує netlib-java. У Scala використовуйте Breeze (також працює від netlib-java)
fommil

4
Використовуючи ND4j та java - мій відносно старий ноутбук завершує запропоноване множення протягом 219 мільйонів. Поки python + numpy завершує його протягом 349 мільйонів
беннілу

2
І лише для додання останнього коментаря щодо використання nd4j, я використовував нативну платформу як її бекенд, якщо я використовую cuda-платформу, вона займає близько 1 мілісекунди
bennyl

Ви десь публікували свій код для орієнтирів?
bruziuz

108

Я автор Java Matrix Benchmark ( JMatBench ), і я висловлю свої думки з цього приводу.

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

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

Бібліотеки, про які я не згадував, демонстрували значні проблеми з продуктивністю або не мали ключових особливостей.


6
Просто подумав, що я зазначу, що ваш орієнтир справді зручний! Дякуємо, що вклали свій час.
hohonuuli

1
Здається, JBLAS підтримує SVD станом на 13 вересня: mikiobraun.github.io/jblas/javadoc/org/jblas/…
Leopd

чудова робота, THX багато.
webpat

Чи є десь бібліотеки, які ви оцінювали, але не опублікували результати та причини кожної?
Кевін Крумвієде

1
MTJ здається покинутим: сховище заархівовано, а останній запис було здійснено у 2016 році.
Даніла П'ятов

51

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


2
надихнувшись вашою роботою, я зробив подібну річ у netlib-java ;-)
fommil

2
Ха-ха, я теж для jeigen :-)
Х'ю Перкінс

JogAmp робить те саме, див. Jogamp-fat.jar. Хороша ідея :)
gouessej

8

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

То що ж це все означає? Ну:

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

Перешкодою для матричних операцій часто є проблеми з локалізацією даних, які виникають, коли вам потрібно пройти обидва рядки за рядками та стовпцями за стовпцями, наприклад, у множенні матриці, оскільки вам потрібно зберігати дані в порядку, що оптимізує те чи інше. Але якщо ви вручну пишете код, іноді можна комбінувати операції з оптимізації місцевості даних (наприклад, якщо ви множите матрицю шляхом її перетворення, ви можете перетворити обхід стовпців у обхід рядків, якщо ви пишете виділену функцію замість комбінування дві функції бібліотеки). Як завжди в житті, бібліотека дасть вам неоптимальну ефективність в обмін на швидший розвиток; вам потрібно вирішити, наскільки важлива для вас ефективність.


8

Я щойно порівняв Apache Commons Math з jlapack.

Тест: сингулярне розкладання значення випадкової матриці 1024x1024.

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

Код октави: A = rand (1024); tic; [U, S, V] = svd (A); toc

час виконання результатів
-------------------------------------------------- -------
Октава 36,34 сек

JDK 1.7u2 64bit
    jlapack dgesvd 37,78 сек
    apache commons math SVD 42.24 sec


JDK 1.6u30 64bit
    jlapack dgesvd 48,68 сек
    apache commons math SVD 50,59 sec

Рідні процедури
Lapack *, на який посилається C: 37,64 сек
Intel MKL 6,89 сек (!)

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

Відмова від відповідальності - я не знавець лінійної алгебри, не приєднаний до жодної з вищезгаданих бібліотек, і це не є суворим орієнтиром. Це "домашній" тест, тому що мені було цікаво порівняти підвищення продуктивності JDK 1.7 до 1.6, а також загальну математику SVD з jlapack.


8

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

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

Швидкий тест шляхом множення двох щільних матриць, тобто:

імпортувати статичні 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
  • У порівнянні з джамою, все швидше :-P
  • У порівнянні з jblas, Джейген не настільки швидкий, але він обробляє рідкісні матриці.
  • У порівнянні з ojalgo, Джейген займає приблизно стільки ж пройденого часу, але використовуючи лише одне ядро, тому Джейген використовує половину загального процесора. Джейген має більш синтаксичний термін, тобто 'mmul' проти 'multiplyRight'

Джейген виглядає приголомшливо! Нещодавно я реалізував Eigen в Java за допомогою JNI та DLL для вирішення дуже великих розріджених матриць. Моя версія з DLL є більш ніж на 20 швидше, ніж паралельний кольт для моїх тестів (понад 8000x8000 матриць). Я б хотів, щоб я знав про Джейгена!
Z boson

6

На Java-версії http://code.google.com/p/java-matrix-benchmark/ існує декілька різних матричних пакетів для кількох різних апаратних конфігурацій. Але це не є заміною робити власний орієнтир.

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

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


4

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

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


1
Ні - la4j дійсно неконкурентоспроможний. Дивіться code.google.com/p/java-matrix-benchmark
Крістофер Меннінг

Це дуже змінилося. З моєї відповіді я випустив дві версії бібліотеки. Поточний реліз становить 0,4,0. І це просто летить.
Володимир Костюков

3

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


Гарна думка! Альфа-етап проекту з обгортками JNI для Atlas: jblas.org . Авторський запис у блозі: mikiobraun.blogspot.com/2008/10/…
dfrankow

3

Ми використовували COLT для деяких досить великих серйозних фінансових розрахунків і були дуже задоволені цим. У нашому високопрофільованому коді нам майже ніколи не доводилося замінювати реалізацію COLT на власну.

В ході їх власного тестування (очевидно, не є незалежним), я думаю, що вони стверджують, що в межах 2-х підрядних процесорів Intel, оптимізованих рукою асемблера. Трюк у тому, щоб добре використовувати його - переконатися, що ви розумієте їх філософію дизайну та уникайте сторонніх розподілів об’єктів.


3

Ви поглянули на бібліотеку ядер Intel Math ? Він стверджує, що перевершує навіть ATLAS . MKL можна використовувати на Java через JNI обгортки.


2
У нас це є. а) ліцензування є більш обмежуючим, ніж Atlas (тому ми не можемо використовувати всі наші комп’ютери); б) це не Java (і, як я вже сказав, у нас є причини хотіти бути на Яві).
дфранков

тобто це не відповідь на моє запитання про бібліотеки Java (але я не маю репутації, щоб це спровокувати).
дфранков

@dfrankow: Я оновив свою відповідь, щоб вирішити вашу проблему щодо використання її на Java.
Зак Скривена

1
+1, якщо це швидкість, яку ви шукаєте, здається, це шлях
Геб Ройер

2
Остання ланка розірвана.
gouessej

2

Спираючись на публікацію Вархана про те, що рідний код, характерний для Pentium, буде краще:


2

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

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


2

Для 3D-графічних додатків реалізація вектора lwjgl.util перевищила вищезгадані jblas в коефіцієнті приблизно 3.

Я зробив 1 мільйон матричних множень vec4 з матрицею 4x4.

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

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


1

Я виявив, що якщо ви створюєте багато матриць високих розмірів, ви можете зробити Jama приблизно на 20% швидше, якщо ви зміните його на використання одновимірного масиву замість двовимірного масиву. Це тому, що Java не підтримує багатовимірні масиви настільки ефективно. тобто. він створює масив масивів.

Кольт це вже робить, але я виявив, що це складніше і потужніше, ніж Джама, що може пояснити, чому прості функції у Colt повільніші.

Відповідь справді залежить від того, що ви робите. Джама не підтримує частину речей, які може зробити Кольт, які можуть зробити щось більше.



0

Існує багато різних вільно доступних бібліотек лінійної алгебри Java. http://www.ujmp.org/java-matrix/benchmark/ На жаль, цей бенчмарк дає лише інформацію про множення матриць (перенесення тесту не дозволяє різним бібліотекам використовувати свої функції дизайну).

На що слід звернути увагу, - це те, як працюють ці лінійні бібліотеки алгебри, коли їх запитують для обчислення різних матричних декомпозицій. http://ojalgo.org/matrix_compare.html


0

Матриця Tookits Java (MTJ) вже згадувалася раніше, але, мабуть, варто згадати ще раз, щоб хтось інший натрапив на цю нитку. Для тих, хто цікавиться, здається, що там також говорять про те, щоб MTJ замінила бібліотеку ліналів у апаш-вісі математики 2.0 , хоча я не впевнений, як це просувається останнім часом.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.