Comment s'assurer que le Java threads s'exécutent sur différents cœurs
Je suis en train d'écrire une application multi-thread en Java afin d'améliorer les performances sur la version séquentielle. C'est une version parallèle de la programmation dynamique de la solution à la 0/1 problème de sac-à-dos. J'ai un processeur Intel Core 2 Duo à la fois avec Ubuntu et Windows 7 Professionnel sur des partitions différentes. Je suis en cours d'exécution dans Ubuntu.
Mon problème est que la version parallèle prend plus de temps que la version séquentielle. Je suis en pensée c'est peut-être parce que les threads sont mappés sur le même thread du noyau ou qu'ils sont affectés à la même base. Est-il une manière que je pourrais veiller à ce que chaque fil de Java correspond à un noyau séparé?
J'ai lu d'autres posts sur ce problème, mais rien ne semble aider.
Ici c'est la fin de main() et tous les de run() pour la KnapsackThread classe (qui s'étend à Fil). Notez que la façon que j'utilise tranche supplémentaire de calculer myLowBound et myHiBound de s'assurer que chaque thread ne se chevauchent pas dans le domaine de la dynProgMatrix. Donc il n'y aura pas de conditions de course.
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;
}
}
}
Mise à jour:
J'ai écrit une autre version du sac à dos qui utilise la force brute. Cette version a très peu de synchronisation parce que j'ai seulement besoin de mettre à jour un bestSoFar variable à la fin d'une seule exécution du thread. Par conséquent, chaque thread assez bien doit exécuter complètement en parallèle à l'exception de cette petite section critique à la fin.
J'ai couru ce rapport à l'ordre de la force brute et encore il prend plus de temps. Je ne vois pas d'autre explication que celle de mon fils sont exécutées de manière séquentielle, soit parce qu'ils sont mappées à la base même ou pour le même thread natif.
N'quelqu'un a des idée?
Il pourrait être utile que si vous postez un lien vers votre KnapsackThread code, et de dire quelque chose à propos de la quantité de fils que vous utilisez. Plus que 4 à 8 threads peut-être un problème sur un core duo,et la synchronisation des blocs peut mettre n'importe quel code 🙂
aussi ce VM utilisez-vous, le soleil sur windows et openjdk sur ubuntu, ou le soleil sur les deux?
J'ai écrit ma version à partir d'une version séquentielle par une autre personne. Il ne permet pas de verrouiller l'accès à la partagé tableau 2d, je n'ai toutefois veiller à ce que chaque thread uniquement écrit pour différents indecies du tableau 2d pour éviter des conditions de course. Je suis en utilisant un thread par core, auquel je n'par: private static KnapsackThread threads[] = new KnapsackThread[ Runtime.getRuntime().availableProcessors() ]; }
Je ne sais pas ce VM, je suis en utilisant en plus de 1.6. J'ai couru à la version de java dans le 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, en mode mixte)
OriginalL'auteur KBP | 2009-12-13
Vous devez vous connecter pour publier un commentaire.
Je doute que ça va être due à l'utilisation de la même base pour tous les threads. La planification jusqu'à l'OS, mais vous devriez être capable de voir ce qui se passe si vous apportez la performance manager pour l'OS, il ne sera probablement montrer comment occupé chaque core est.
Raisons possibles pour qu'il prennent de plus en plus:
Nous n'avons pas vraiment vu le code nécessaire de savoir. Nous ne savons pas comment big le
threads
tableau, à moins que j'ai raté quelque chose.(
Runtime.availablePrcoessors
donnera le nombre de threads matériels.)Runtine.availableProcessors me donne le nombre de cœurs droit? pas de fils
Comme le nom de la méthode déjà des conseils, elle renvoie le nombre de processeurs disponibles (logique des unités de traitement, de cœurs que vous voulez), pas de fils.
OriginalL'auteur Jon Skeet
J'ai eu le même problème pendant un certain temps. J'ai eu un gourmandes programme que j'ai divisé en 2 fils (double core CPU), mais un beau jour, alors que le traitement des données plus, il s'est juste arrêté à l'aide de deux noyaux. J'ai juste soulevé le tas mem taille (
-Xmx1536m
dans mon cas), et il a bien fonctionné de nouveau.OriginalL'auteur arm3nio
Je vous suggère de jeter un oeil à combien de temps il faut pour chacun de vos threads de travail avant de résilier. Peut-être l'un des fils a une tâche beaucoup plus difficile. Si c'est le cas, alors la surcharge causée par la synchronisation et ainsi de suite permettra de prendre facilement ce que vous avez gagné de filetage.
OriginalL'auteur Buhb