Multi-core Java program with native code

I use my own C ++ library inside a Java program. The Java program is written to use multi-core systems, but it does not scale: the best speed is about 6 cores, i.e. Adding more cores slows it down. My tests show that calling the native code itself is causing a problem, so I want to make sure that different threads access different instances of the native library and, therefore, remove any hidden (memory) dependency between parallel tasks. In other words, instead of a static block

static { System.loadLibrary("theNativeLib"); } 

I want several instances of the library to load dynamically for each thread. The main question , if at all possible. And then how to do it!

Notes: - I have implementations in Java 7 fork / join, as well as Scala / akka. Therefore, any help on each platform is appreciated. - Parallel tasks are completely independent. In fact, each task can create a couple of new tasks, and then ends; no additional dependency!

Here is a fork / join-style test program in which processNative is basically a bunch of its own calls:

 class Repeater extends RecursiveTask<Long> { final int n; final processor mol; public Repeater(final int m, final processor o) { n=m; mol = o; } @Override protected Long compute() { processNatively(mol); final List<RecursiveTask<Long>> tasks = new ArrayList<>(); for (int i=n; i<9; i++) { tasks.add(new Repeater(n+1,mol)); } long count = 1; for(final RecursiveTask<Long> task : invokeAll(tasks)) { count += task.join(); } return count; } } private final static ForkJoinPool forkJoinPool = new ForkJoinPool(); public void repeat(processor mol) { final long middle = System.currentTimeMillis(); final long count = forkJoinPool.invoke(new Repeater(0, mol)); System.out.println("Count is "+count); final long after = System.currentTimeMillis(); System.out.println("Time elapsed: "+(after-middle)); } 

Put it another way: If I have N threads that use the native library, what happens if each of them calls System.loadLibrary ("theNativeLib"); dynamically, instead of calling it once in a static block? Do they share the library? If so, how can I trick the JVM into seeing it as N different libraries loaded independently? (The value of N is not known statically)

+7
source share
2 answers

The javadoc for System.loadLibrary indicates that it matches the call to Runtime.getRuntime().loadLibrary(name) . The loadLibrary for this loadLibrary ( http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#loadLibrary(java.lang.String) ) states: "If this method is called more than once with the same library name, the second and subsequent calls are ignored. "so it seems like you cannot load the same library more than once. From the point of view of cheating the JVM there are several instances in thinking, I cannot help you.

+2
source

You need to make sure that you do not have a bottle neck on any shared resources. for example, say that you have 6 hyperlinked kernels, you may find that 12 threads are optimal or you may find that 6 threads are optimal (and each thread has a dedicated core).

If you have a difficult floating point procedure, chances are that hyperthreading will be slower rather than faster.

If you use the entire cache, trying to use more can slow down your system. If you use the CPU limit for the main memory bandwidth, trying to use more bandwidth can slow down your computer.

But then, how can I refer to different instances? I mean that loaded classes will have the same names and packages, right? What happens in general if you load two dynamic libraries containing classes with the same names and packages?

There is only one instance; you cannot load a DLL more than once. If you want to create a different data set for each stream, you need to do it from the outside to the library and transfer it to the library so that each stream can work with different data.

0
source

All Articles