Производительность JNI против JNA
У нас есть собственное приложение c/asm, использующее GPU(OpenCL) для больших данных encrypt/decrypt с определенным методом, и оно просто отлично работает, никаких проблем. Часть проекта (web и дистрибутив) разрабатывается JEE, и нам просто нужно вызвать собственное приложение/библиотеку.
Мы попытались вызвать его как отдельный внешний процесс, используя класс Process. Проблема в том, что мы не можем контролировать приложение(события, обработчики, потоки и т. д...). Мы также попытались просто переключить код C в Java-код, но производительность умерла. Кроме запуска машинного кода как процесса, я думаю о JNA и JNI, но есть некоторые вопросы.
Вопросы:
- для лучшего (более быстрого) решения для чтения / записи можно ли обмениваться данными с помощью прямой (неуправляемой) памяти [Java (
ByteBuffer#allocateDirect())] как в JNI, так и в JNA? - Можно ли управлять процессом и обрабатывать его с помощью собственного кода, а также обращаться к GPU(shared) memory через Java-код (OpenCL lib)?
- как насчет представление? Является ли JNA быстрее, чем JNI?
У нас есть два кластерных устройства AMD W7000 на Redhat Linux6 x64.
4 ответов:
JNA гораздо медленнее, чем JNI, но гораздо легче. Если производительность не является проблемой, используйте JNA.
Использование прямых буферов имеет то преимущество, что наиболее важные операции не используют JNI или JNA и, таким образом, быстрее. Они используют встроенные средства, когда они превращаются в одиночные инструкции машинного кода.
Если код Java значительно медленнее, чем C, то, скорее всего, код недостаточно оптимизирован. Как правило, GPU должен делать ВСЮ работу, так что если Java немного медленнее, это это не должно иметь большого значения.
Например, если вы проводите 99% времени в GPU, а Java занимает в два раза больше времени, общее время будет 99+2% или 1% медленнее.
Тяжелый хруст чисел выполняется в C / GPU, все, что делает ваш интерфейс Java C, - это перемешивание данных. Я был бы удивлен, если бы это оказалось узким местом.
В любом случае, напишите Самый простой и понятный код, который выполняет эту работу. Если окажется, что производительности недостаточно, измерьте, где находятся узкие места, и устраняйте их по одному, пока производительность не будет в порядке. Время программиста гораздо более ценно, чем компьютерное время, за исключением очень особых обстоятельств.
Как производительность JNA сравнивается с пользовательской JNI?
Прямое отображение JNA может обеспечить производительность, близкую к производительности пользовательского JNI. Почти все функции сопоставления типов интерфейса доступны, хотя автоматическое преобразование типов, вероятно, потребует некоторых накладных расходов.
Накладные расходы на вызов для одного собственного вызова с использованием отображения интерфейса JNA могут быть на порядок (~10 раз) больше времени, чем эквивалентный пользовательский JNI (действительно ли это так в контексте вашего приложения-другой вопрос). В грубых терминах накладные расходы на вызов составляют порядка сотен микросекунд вместо десятков микросекунд. Обратите внимание, что это накладные расходы на вызов, а не Общее время вызова. Эта величина характерна для различий между системами, использующими динамически поддерживаемую информацию о типах, и системами, в которых информация о типах компилируется статически. JNI hard-коды типа информации в методе вызова, где JNA отображение интерфейса динамически определяет информацию о типе во время выполнения.
Вы можете ожидать ускорения порядка порядка величины, движущегося к прямому отображению JNA, и фактора двух или трех, движущихся оттуда к пользовательскому JNI. Фактическая разница будет варьироваться в зависимости от сигнатур использования и функций. Как и в любом процессе оптимизации, вы должны сначала определить, где вам нужно увеличить скорость, а затем посмотреть, насколько велика разница, выполняя целевые оптимизации. Легкость в обращении Программирование всего на Java обычно перевешивает небольшой прирост производительности при использовании пользовательского JNI.
Я разработал простую dll и поставил пустую функцию, которая ничего не делает. Затем я вызвал эту функцию из dll с JNA, а также JNI, поэтому я попытался вычислить стоимость их вызова. При просмотре производительности после многих вызовов JNI был в 30-40 раз быстрее, чем JNA.
Comments