具有本机代码的多核Java程序

时间:2012-08-20 13:00:08

标签: java parallel-processing scalability multicore native-code

我在Java程序中使用本机C ++库。编写Java程序是为了利用多核系统,但它不能扩展:最佳速度是大约6个核心,即添加更多核心会降低它的速度。我的测试表明,对本机代码本身的调用会导致问题,所以我想确保不同的线程访问本机库的不同实例,从而删除并行任务之间的任何隐藏(内存)依赖关系。 换句话说,而不是静态块

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

我希望为每个线程动态加载库的多个实例。主要的问题是否可行。然后怎么做!

注意: - 我在Java 7 fork / join以及Scala / akka中实现了。所以对每个平台的任何帮助表示赞赏。 - 并行任务完全独立。实际上,每个任务可能会创建一些新任务然后终止;没有进一步的依赖!

以下是fork / join样式的测试程序,其中processNative基本上是一堆本机调用:

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));
}

区别对待: 如果我有N个线程使用本机库,如果每个线程调用System.loadLibrary(“theNativeLib”)会发生什么?动态,而不是在静态块中调用一次?他们会分享图书馆吗?如果是的话,我怎么能欺骗JVM看到它独立加载N个不同的库? (N的值不是静态知道的)

2 个答案:

答案 0 :(得分:2)

System.loadLibrary的javadoc声明它与调用Runtime.getRuntime().loadLibrary(name)相同。这个loadLibraryhttp://docs.oracle.com/javase/7/docs/api/java/lang/System.html#loadLibrary(java.lang.String))的javadoc声明“如果使用相同的库名称多次调用此方法,则忽略第二次和后续调用。”,所以看起来你不能多次加载同一个库。在愚弄JVM时,我认为有多个实例,我无法帮助你。

答案 1 :(得分:0)

您需要确保在任何共享资源上没有瓶颈。例如假设您有6个超线程核心,您可能会发现12个线程是最佳的,或者您可能会发现6个线程是最佳的(并且每个线程都有一个专用核心)

如果你有一个沉重的浮点例程,那么超线程可能会更慢而不是更快。

如果您正在使用所有缓存,尝试使用更多缓存可能会降低系统速度。如果您使用CPU的主内存带宽限制,尝试使用更多带宽可能会降低您的机器速度。

  

但是,我怎样才能引用不同的实例?我的意思是加载的类将具有相同的名称和包,对吧?如果加载包含具有相同名称和包的类的两个动态库,通常会发生什么?

只有一个实例,您不能多次加载DLL。如果要为每个线程构建不同的数据集,则需要在库外部执行此操作并将其传递给库,以便每个线程可以处理不同的数据。