如何确保Java线程在不同的内核上运行
问题内容:
我正在用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密集型任务,创建的线程数与内核数一样多。