Wie sichergestellt werden Java-threads auf verschiedenen Kerne
Schreibe ich eine multi-threaded-Applikation in Java, um zur Verbesserung der Leistung über die sequentielle version. Es ist eine parallel-version der dynamischen Programmierung Lösung des 0/1 knapsack problem. Ich habe einen Intel Core 2 Duo, sowohl mit Ubuntu und Windows 7 Professional auf verschiedenen Partitionen. Ich bin auch unter Ubuntu.
Mein problem ist, dass die parallele version tatsächlich länger dauert als die sequentielle version. Ich denke, dies kann sein, weil die threads sind alle zugeordnet, die den gleichen kernel thread oder, dass Sie verteilt werden, auf dem gleichen Kern. Gibt es eine Möglichkeit, ich könnte dafür sorgen, dass jedes Java-thread-Karten auf einen separaten core?
Habe ich andere Beiträge gelesen über dieses problem, aber nichts scheint zu helfen.
Hier ist das Ende von main() und alle von run() für die KnapsackThread Klasse (extends Thread). Beachten Sie, dass Sie die Art, wie ich mit in Scheiben schneiden und extra zu berechnen myLowBound und myHiBound sicherzustellen, dass jeder thread überschneiden sich nicht in der Domäne des dynProgMatrix. Es gibt also keine race conditions.
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;
}
}
}
Update:
Ich geschrieben habe, eine andere version der Ranzen verwendet brute-force. Diese version hat sehr wenig Synchronisation, da brauche ich nur ein update bestSoFar Variablen am Ende von einen einzigen thread der Ausführung. Daher kann jeder thread ziemlich viel ausführen sollte vollständig in parallele, außer, dass die kleinen kritischen Abschnitt am Ende.
Lief ich dies gegenüber der sequentiellen brute-force-und trotzdem dauert es länger. Ich sehe keine andere Erklärung als die, dass meine threads werden sequenziell ausgeführt werden, weil Sie entweder zugeordnet werden, um den gleichen Kern oder der gleichen nativen thread.
Hat jemand eine Einsicht?
Es könnte nützlich sein, wenn Sie post einen link zu Ihrer KnapsackThread code, und sagen etwas über die Menge der threads, die Sie verwenden. Mehr als 4-8 threads, die möglicherweise ein problem auf einem core duo und synchronisierte Blöcke können bringen jeden nieder, der code 🙂
auch welche VM benutzt du, Sonne, die auf windows und openjdk auf ubuntu, oder genießen Sie die Sonne auf beiden?
Ich schrieb meine version aus einer sequentiellen version von einer anderen person. Es sperrt nicht den Zugriff auf den freigegebenen 2d-array, Tue ich jedoch sicherzustellen, dass jeder thread nur schreibt, um verschiedene indecies des 2d-array, um Wettlaufsituationen zu vermeiden. Ich bin mit einem thread pro core, die ich tun von: private static KnapsackThread threads[] = new KnapsackThread[ Laufzeit.getRuntime().availableProcessors() ]; }
Ich weiß nicht, was VM verwende ich außerdem 1.6. Ich lief die java -version im terminal: java version "1.6.0_16" Java(TM) SE Runtime Environment (build 1.6.0_16-b01) Java HotSpot(TM) Server VM (build 14.2-b01, mixed mode)
InformationsquelleAutor KBP | 2009-12-13
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich bezweifle, dass es aufgrund der mit dem gleichen Kern für alle threads. Die Planung ist bis auf das OS, aber Sie sollten in der Lage sein zu sehen, was Los ist, wenn Sie bringen Sie die performance manager für die OS - es wird in der Regel zeigen, wie viel in jedem Kern ist.
Mögliche Gründe dafür länger:
Wir haben nicht wirklich genug gesehen, um code zu kennen. Wir wissen nicht, wie groß die
threads
array ist, es sei denn, ich habe etwas verpasst.(
Runtime.availablePrcoessors
geben die Anzahl der hardware-threads.)Runtine.availableProcessors gibt mir die Anzahl der Kerne richtig? nicht-threads
Wie der name der Methode schon andeutet, es gibt die Anzahl der verfügbaren Prozessoren (logical processing units, CPU-Kernen, wie Sie wollen), nicht threads.
InformationsquelleAutor Jon Skeet
Ich hatte das gleiche problem für eine Weile. Ich hatte eine CPU-hungrigen Programm, das ich gliedert sich in 2 threads, (Doppel-Kern CPU), aber einer schöner Tag,, während der Verarbeitung ein paar Daten mehr, es gerade aufgehört mit beiden cores. Ich hob nur den heap mem size (
-Xmx1536m
in meinem Fall), und es funktionierte wieder.InformationsquelleAutor arm3nio
Ich schlage vor, Sie nehmen einen Blick an, wie lange es dauert, für jede Ihrer worker-threads, bevor Sie kündigen. Vielleicht ist einer der threads hat eine viel schwierigere Aufgabe. Wenn das der Fall ist, dann ist der overhead, verursacht durch die Synchronisation und so weiter werden einfach Essen, was Sie gewonnen haben von threading.
InformationsquelleAutor Buhb