当前位置: 首页 > 面试题库 >

如何确保Java线程在不同的内核上运行

华昕
2023-03-14
问题内容

我正在用Java编写多线程应用程序,以提高顺序版本的性能。它是针对0/1背包问题的动态编程解决方案的并行版本。我有一个Intel Core 2
Duo,在不同的分区上都具有Ubuntu和Windows 7 Professional。我在Ubuntu中运行。

我的问题是并行版本实际上比顺序版本花费的时间更长。我认为这可能是因为所有线程都被映射到同一个内核线程,或者它们被分配给了同一个内核。有没有办法确保每个Java线程都映射到一个单独的核心?

我已经阅读了有关此问题的其他帖子,但似乎无济于事。

这是KnapsackThread类(扩展Thread)的main()和run()的结尾。请注意,他们使用切片及其他方法计算myLowBound和myHiBound的方式确保了每个线程在dynProgMatrix的域中不会重叠。因此,将没有比赛条件。

    dynProgMatrix = new int[totalItems+1][capacity+1];
    for (int w = 0; w<= capacity; w++)
        dynProgMatrix[0][w] = 0;
    for(int i=0; i<=totalItems; i++)
        dynProgMatrix[i][0] = 0;
    slice = Math.max(1,
            (int) Math.floor((double)(dynProgMatrix[0].length)/threads.length));
    extra = (dynProgMatrix[0].length) % threads.length;

    barrier = new CyclicBarrier(threads.length);
    for (int i = 0; i <  threads.length; i++){
        threads[i] = new KnapsackThread(Integer.toString(i));
    }
    for (int i = 0; i < threads.length; i++){
        threads[i].start();
    }

    for (int i = 0; i < threads.length; i++){
        try {
            threads[i].join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

public void run(){
    int myRank = Integer.parseInt(this.getName());

    int myLowBound;
    int myHiBound;

    if (myRank < extra){
        myLowBound = myRank * (slice + 1);
        myHiBound = myLowBound + slice;
    }
    else{
        myLowBound = myRank * slice + extra;
        myHiBound = myLowBound + slice - 1;
    }

    if(myHiBound > capacity){
        myHiBound = capacity;
    }

    for(int i = 1; i <= totalItems; i++){
        for (int w = myLowBound; w <= myHiBound; w++){

            if (allItems[i].weight <= w){
               if (allItems[i].profit + dynProgMatrix[i-1][w-allItems[i].weight]
                        > dynProgMatrix[i-1][w])
                {
                    dynProgMatrix[i][w] = allItems[i].profit +
                                      dynProgMatrix[i-1][w- allItems[i].weight];
                }
                else{
                    dynProgMatrix[i][w] = dynProgMatrix[i-1][w];
                }
            }
            else{
                dynProgMatrix[i][w] = dynProgMatrix[i-1][w];
            }
        }
        // now place a barrier to sync up the threads
        try {
            barrier.await(); 
        } catch (InterruptedException ex) { 
            ex.printStackTrace();
            return;
        } catch (BrokenBarrierException ex) { 
            ex.printStackTrace(); 
            return;
        }
    }
}

更新:

我已经编写了使用蛮力的背包的另一个版本。这个版本几乎没有同步,因为我只需要在单线程执行结束时更新bestSoFar变量。因此,每个线程几乎都应该完全并行执行,除了最后的那个小关键部分。

我将其与顺序蛮力进行了比较,但仍然需要更长的时间。除了将我的线程按顺序运行之外,没有其他解释,这是因为它们被映射到相同的内核或相同的本机线程。

有人有见识吗?


问题答案:

我怀疑这将归因于所有线程都使用相同的内核。调度取决于操作系统,但是如果启动操作系统的性能管理器,您应该能够看到正在发生的事情-
它通常会显示每个内核的繁忙程度。

可能需要更长的时间的原因:

  • 大量同步(必要或不必要)
  • 任务花费的时间如此之短,以至于线程创建花费了大量时间
  • 上下文切换,如果您创建的线程过多-对于CPU密集型任务,创建的线程数与内核数一样多。


 类似资料:
  • 然而,我很好奇如何确保这4个实例完全运行在4个不同的核心上?一个实例在启动时如何决定运行在其上的核心?

  • 给定打印字母a-C的三个线程1-3,如何保证输出顺序? 我希望线程的输出是“abcabc”

  • 我希望澄清我对.NET多线程的理解,特别是.NET方法创建的线程可能在多处理器/核系统中的不同处理器或核上同时执行。 在.NET TPL框架中,可以使用Parallel.Invoke或Task.Factory.StartNew方法来实现某种并行性。 我的理解是,在这两种情况下.NET都创建了新任务(在后台为Parallel.Invoke),然后.NET环境将这些任务分配给后台的托管线程,这些线程再

  • docker如何在Debian主机上运行,或者在容器中运行OpenSUSE?它使用不同的内核,具有不同的模块。另外,老版本的Debian使用了老版本的内核,那么如何在3.10+版本的内核上运行它呢?旧的内核只有旧的内置功能,旧的发行版如何管理新的功能?这里面有什么“诀窍”?

  • 我正在运行RxJava并创建一个主题以使用方法生成数据。我正在使用Spring。 这是我的设置: 在RxJava流上生成新数据的方式是通过Autowire private SubjectObserver SubjectObserver,然后调用SubjectObserver。发布(newDataObjGenerated) 无论我为subscribeOn()指定了什么 Schedulers.io()

  • 问题内容: 我可以使用一台可以访问10个内核的机器-我想实际使用它们。我习惯在自己的机器上做的事情是这样的: 我要执行10个文件-我们将其称为blah00.fa,blah01.fa,… blah09.fa。 这种方法的问题在于,myProgram一次仅使用1个内核,并且在多核计算机上这样做,我将一次使用10个内核,因此我不会使用mahcine来其最大能力。 如何更改脚本,以使其同时运行所有10个.