Подтвердить что ты не робот

Производительность JNI против JNA

У нас есть собственное приложение c/asm, использующее GPU (OpenCL) для больших encrypt/decrypt данных с определенным методом, и оно просто отлично работает, без проблем. Часть проекта (сеть и распространение) разрабатывается JEE, и нам просто нужно вызвать собственное приложение/библиотеку.

Мы попытались назвать это разделенным-внешним процессом, используя класс Process. Проблема в том, что мы не можем управлять приложением (событие, обработчики, потоки и т.д.). Мы также попытались просто переключить код C на Java-код, но производительность умерла. За исключением запуска собственного кода как процесса, я думаю о JNA и JNI, но есть некоторые вопросы.

Вопросы:

  • Для лучшего (более быстрого) решения для чтения/записи возможно обмен данными с помощью прямой (неуправляемой) памяти [Java (ByteBuffer#allocateDirect())] как в JNI, так и в JNA?
  • Возможно ли управлять и обрабатывать процесс по собственному коду и получать доступ к памяти GPU (совместно используемой) через Java-код (OpenCL lib)?
  • Как насчет производительности? Является ли JNA быстрее, чем JNI?

У нас есть два кластерных устройства AMD W7000 на Redhat Linux6 x64.

4b9b3361

Ответ 1

JNA намного медленнее, чем JNI, но намного проще. Если производительность не является проблемой, используйте JNA.

Использование прямых буферов имеет то преимущество, что наиболее важные операции не используют JNI или JNA и, следовательно, быстрее. Они используют встроенные средства, когда они превращаются в отдельные инструкции машинного кода.

Если код Java значительно медленнее C, скорее всего, код недостаточно оптимизирован. Как правило, GPU должен выполнять всю работу, поэтому, если Java немного медленнее, это не должно иметь большого значения.

например. если вы тратите 99% времени на GPU, а Java занимает вдвое больше, то общее количество будет на 99 + 2% или на 1% медленнее.

Ответ 2

Тяжелое хрустение числа выполняется в C/GPU, все ваши интерфейсы Java ↔ C - это входы/выходы в случайном порядке. Я был бы удивлен, если это узкое место.

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

Ответ 3

Я разработал простую dll и поместил пустую функцию, которая ничего не делает. Затем я вызвал эту функцию из dll с помощью JNA, а также JNI, поэтому я попытался рассчитать стоимость их вызова. При просмотре производительности после многих вызовов JNI был в 30-40 раз быстрее, чем JNA.

Ответ 4

Из Официальные FAQ JNA:

Как производительность JNA сравнивается с пользовательским JNI?

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

Накладные расходы на вызов для одного собственного вызова с использованием сопоставления интерфейса JNA могут быть на порядок (~ 10X) больше времени, чем эквивалентный пользовательский JNI (независимо от того, действительно ли он в контексте вашего приложения является другим вопросом). В исходных условиях накладные расходы на звонки составляют порядка сотен микросекунд вместо десятков микросекунд. Обратите внимание, что это служебные данные вызова, а не общее время вызова. Эта величина типична для разницы между системами, использующими динамически поддерживаемую информацию о типе и системами, где информация о типе статически компилируется. Информация о жестких кодах JNI типа в вызове метода, где сопоставление интерфейса JNA динамически определяет информацию о типе во время выполнения.

Вы можете ожидать, что ускорение примерно на порядок приведет к прямому картированию JNA, а два-три фактора переместится оттуда к пользовательскому JNI. Фактическая разница будет различаться в зависимости от использования и подписи функций. Как и в любом процессе оптимизации, сначала необходимо определить, где вам нужно увеличить скорость, а затем посмотреть, какая разница между ними, путем целенаправленной оптимизации. Простота программирования всего на Java обычно превосходит малую прирост производительности при использовании пользовательского JNI.