JNI vs. JNA 性能

我们有一个利用GPU(OpenCL)的本机应用程序,用于具有特定方法的大数据,并且它工作完美,没有问题。项目的一部分(Web和发行版)是由 开发,我们只需要调用本机应用程序/库。c/asmencrypt/decryptJEE

我们尝试使用类将其称为分离的外部进程。问题是我们无法控制应用程序(事件,处理程序,线程等)。我们还尝试将C代码转换为Java代码,但性能下降。除了将本机代码作为进程运行之外,我正在考虑JNA和JNI,但是存在一些问题。Process

问题:

  1. 为了更好(更快)的读/写解决方案,是否可以在JNI和JNA中通过直接(非托管)内存[Java()]交换数据?ByteBuffer#allocateDirect()
  2. 是否可以通过本机代码管理和处理进程,并通过 Java 代码(OpenCL lib)访问 GPU(共享)内存?
  3. 性能如何?JNA比JNI快吗?

我们在 Redhat Linux6 x64 上有两个 AMD W7000 群集设备。


答案 1

JNA比JNI慢得多,但要容易得多。如果性能不是问题,请使用 JNA。

使用直接缓冲区的优点是,最关键的操作不使用 JNI 或 JNA,因此速度更快。当它们被转换为单个机器代码指令时,它们使用内在函数。

如果 Java 代码明显慢于 C 语言,则可能是代码没有得到足够的优化。一般来说,GPU应该完成所有的工作,所以如果Java有点慢,这应该不会有太大的区别。

例如,如果您将99%的时间花在GPU上,而Java花费的时间是其两倍,则总时间将减慢99 + 2%或1%。


答案 2

来自JNA的官方常见问题解答

JNA 的性能与自定义 JNI 相比如何?

JNA 直接映射可以提供接近自定义 JNI 的性能。接口映射的几乎所有类型映射功能都可用,尽管自动类型转换可能会产生一些开销。

使用 JNA 接口映射进行单个本机调用的调用开销可能比等效的自定义 JNI 大一个数量级 (~10X)(在应用程序的上下文中它是否实际存在是另一个问题)。从原始角度来看,调用开销约为数百微秒,而不是数十微秒。请注意,这是呼叫开销,而不是总呼叫时间。此量级是使用动态维护的类型信息的系统与静态编译类型信息的系统之间的差异的典型。JNI 在方法调用中对类型信息进行硬编码,其中 JNA 接口映射在运行时动态确定类型信息。

您可能希望将加速大约一个数量级,移动到 JNA 直接映射,以及从那里移动到自定义 JNI 的两到三倍。实际差异将因使用情况和函数签名而异。与任何优化过程一样,您应该首先确定需要提高速度的位置,然后通过执行有针对性的优化来查看差异有多大。在使用自定义 JNI 时,在 Java 中编写所有内容的易用性通常超过小的性能提升。


推荐