使用本机接口的多个java线程与多线程本机的单个java线程相比

Multiple java threads using native interface vs single java thread for multi threaded native

本文关键字:线程 java 本机 多线程 单个 接口      更新时间:2023-10-16

我正在为一个项目做准备,该项目使用JNI来加速物理建模的一些计算。Native part对一组数组进行计算,每个数组都有超过10M个元素。

问题:哪个选项更适合性能:

1) 使用java中的8个线程,每个线程通过本机调用(jni-->c++)处理数组的1/8部分。我是否需要将整个阵列裁剪成更小的阵列,以防止不必要的阵列复制?

2) 在java中使用单线程来调用8线程的本机(pthreads?)我可以使用指针算法只选择线程中需要使用的部分吗?

我需要处理数组的单个副本(或原始副本),c++线程是否为自己复制整个数组?java线程呢?哪一个不是复制的,我会用那个。

注意:我使用GetPrimitiveArrayCritical()来防止JNI接口的数组复制(在原始接口上工作)。计算需要足够长的时间,可以忽略JNI开销。

GetPrimitiveArrayCritical()固定java数组,因此GC停止工作,直到本机函数释放它,这会影响其他java线程的访问权限吗?

如果extern "C"很重要,则实际上所有内容都在其中

操作系统:64位windows7CPU:fx8150jvm:64位GCC:64位

谢谢。

从设计的角度来看,我更喜欢方法#1,因为这意味着您不必管理JNI代码中的线程。这遵循了"单一责任原则":只有当您的算法发生变化时,您的本地代码才需要更改。我还认为Java提供的工具(线程池和期货)比直接线程更容易使用。

但是,如果您这样做,您应该特别注意关于从多个线程固定和取消固定数组的警告。

IMO的一个更好的方法是分配直接ByteBuffer,并使用GetDirectBufferAddress从JNI访问它。这将允许您使用Java端线程池来管理工作,并消除任何本机端对缓冲区副本的担忧。