Как обеспечить работу потоков Java на разных ядрах
Я пишу многопоточное приложение на Java для повышения производительности по сравнению с последовательной версией. Это параллельная версия решения динамического программирования для задачи о ранце 0/1. У меня Intel Core 2 Duo с Ubuntu и Windows 7 Professional на разных разделах. Я бегу в Ubuntu.
Моя проблема в том, что параллельная версия на самом деле занимает больше времени, чем последовательная версия. Я думаю, что это может быть связано с тем, что все потоки отображаются в один и тот же поток ядра или что они распределены одному и тому же ядру. Есть ли способ, которым я мог бы гарантировать, что каждый поток Java отображается на отдельное ядро?
Я читал другие посты об этой проблеме, но, похоже, ничего не помогает.
Здесь конец main () и все run () для класса KnapsackThread (который расширяет Thread). Обратите внимание, что они, как я использую slice и extra для вычисления 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 только в конце выполнения одного потока. Следовательно, каждый поток должен выполняться полностью параллельно, за исключением небольшого критического раздела в конце.
Я управлял этим против последовательной грубой силы, и все же это занимает больше времени. Я не вижу другого объяснения, кроме того, что мои потоки выполняются последовательно, либо потому, что они сопоставлены с тем же ядром или с тем же собственным потоком.
У кого-нибудь есть понимание?