Лучшие практики Java для векторизованных вычислений
Я исследую методы вычисления дорогих векторных операций в Java, например, точечные произведения или умножения между большими матрицами. Здесь есть несколько хороших тем на эту тему, как это и это.
Похоже, что нет надежного способа иметь код компиляции JIT для использования векторных инструкций ЦП (SSE2, AVX, MMX...). Более того, высокопроизводительные библиотеки линейной алгебры (ND4J, jblas, ...) фактически делают вызовы JNI к библиотекам BLAS/LAPACK для основных подпрограмм. И я понимаю, что пакеты BLAS/LAPACK де-факто являются стандартным выбором для вычислений с линейной алгеброй.
С другой стороны, другие (JAMA, ...) реализуют алгоритмы на чистой Java без native
звонки.
Мои вопросы:
- Каковы лучшие практики здесь?
- Делает
native
звонки в BLAS/LAPACK на самом деле рекомендуемый выбор? Есть ли другие библиотеки, которые стоит рассмотреть? - Затраты на вызовы JNI незначительны по сравнению с увеличением производительности? У кого-нибудь есть опыт относительно того, где находится порог (например, насколько маленьким должен быть ввод, чтобы сделать вызовы JNI более дорогими, чем обычная процедура Java?)
- Насколько велик компромисс между переносимостью?
Я надеюсь, что этот вопрос может быть полезен как для тех, кто разрабатывает свои собственные процедуры вычислений, так и для тех, кто просто хочет сделать осознанный выбор между различными реализациями.
Идеи приветствуются!
1 ответ
Нет четких лучших практик для каждого случая. Можно ли / нужно ли использовать чистое решение Java (без использования SIMD-инструкций) или (оптимизированный с помощью SIMD) нативный код через JNI, зависит от вашего конкретного приложения и, в частности, от размера ваших массивов и возможных ограничений в целевой системе.
- Может быть требование, что вам не разрешено устанавливать определенные нативные библиотеки в целевой системе, а BLAS еще не установлен. В этом случае вам просто нужно использовать библиотеку Java.
- Чистые библиотеки Java, как правило, работают лучше для массивов, длина которых намного меньше 100, и в какой-то момент после этого вы получаете лучшую производительность, используя нативные библиотеки через JNI. Как всегда, ваш пробег может отличаться.
Соответствующие тесты были выполнены (в случайном порядке):
- http://ojalgo.org/performance_ejml.html
- http://lessthanoptimal.github.io/Java-Matrix-Benchmark/
- Производительность математических библиотек Java?
Эти критерии могут быть запутанными, поскольку они информативны. Одна библиотека может быть быстрее для некоторых операций и медленнее для других. Также имейте в виду, что для вашей системы может быть доступно несколько реализаций BLAS. В настоящее время на моей системе установлены 3 бла, атласа и openblas. Помимо выбора библиотеки Java, обертывающей реализацию BLAS, вы также должны выбрать базовую реализацию BLAS.
Этот ответ содержит довольно актуальный список, за исключением того, что он не упоминает nd4j, который является довольно новым. Имейте в виду, что jeigen зависит от eigen, а не от BLAS.