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



我在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("NativeLib")会发生什么;动态地,而不是在静态块中调用它一次?他们会共享图书馆吗?如果是,我如何欺骗JVM,使其将其视为独立加载的N个不同库?(N的值不是静态已知的)

System.loadLibrary的javadoc声明它与调用Runtime.getRuntime().loadLibrary(name)相同。此loadLibrary的javadoc(http://docs.oracle.com/javase/7/docs/api/java/lang/System.html#loadLibrary(java.lang.String))声明"如果用相同的库名称多次调用此方法,则第二次和后续调用将被忽略。",因此似乎不能多次加载同一个库。就欺骗JVM使其认为存在多个实例而言,我在这方面帮不了你。

您需要确保不会对任何共享资源造成瓶颈。例如,假设你有6个超线程核心,你可能会发现12个线程是最优的,或者你可能会找到6个线程是最佳的(每个线程都有一个专用核心)

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

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

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

只有一个实例,不能多次加载DLL。如果你想为每个线程构造一个不同的数据集,你需要在库的外部进行,并将其传递给库,这样每个线程就可以处理不同的数据。

相关内容

  • 没有找到相关文章

最新更新