Pourquoi ce code Java n'utilise-t-il pas tous les cœurs de processeur?
Le joint simple code Java doit charger tous les processeurs disponibles noyau lors du démarrage avec les bons paramètres. Ainsi, par exemple, vous démarrez avec
java VMTest 8 int 0
et il va commencer à 8 threads qui ne font rien d'autre que de la boucle et en ajoutant 2 un entier. Quelque chose qui fonctionne dans les registres et pas même alloue de la mémoire.
Le problème auquel nous faisons face aujourd'hui est que nous n'obtenons pas un 24 de base de la machine de chargement (AMD 2 prises de courant avec 12 cœurs de chacun), lors de l'exécution de ce programme simple (avec 24 threads bien sûr). Des choses semblables se produisent avec 2 programmes de chaque 12 threads ou les petites machines.
Si nos soupçons, c'est que la JVM (Sun JDK 6u20 sur Linux x64), ne l'est pas.
Quelqu'un a-voir des choses semblables ou a la possibilité d'exécuter et de le signaler si oui ou non il fonctionne bien sur sa machine (>= 8 cœurs seulement s'il vous plaît)? Des idées?
J'ai essayé que sur Amazon EC2 avec 8 cœurs trop, mais la machine virtuelle semble différent d'un véritable boîte, de sorte que le chargement se comporte totalement étrange.
package com.test;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class VMTest
{
public class IntTask implements Runnable
{
@Override
public void run()
{
int i = 0;
while (true)
{
i = i + 2;
}
}
}
public class StringTask implements Runnable
{
@Override
public void run()
{
int i = 0;
String s;
while (true)
{
i++;
s = "s" + Integer.valueOf(i);
}
}
}
public class ArrayTask implements Runnable
{
private final int size;
public ArrayTask(int size)
{
this.size = size;
}
@Override
public void run()
{
int i = 0;
String[] s;
while (true)
{
i++;
s = new String[size];
}
}
}
public void doIt(String[] args) throws InterruptedException
{
final String command = args[1].trim();
ExecutorService executor = Executors.newFixedThreadPool(Integer.valueOf(args[0]));
for (int i = 0; i < Integer.valueOf(args[0]); i++)
{
Runnable runnable = null;
if (command.equalsIgnoreCase("int"))
{
runnable = new IntTask();
}
else if (command.equalsIgnoreCase("string"))
{
runnable = new StringTask();
}
Future<?> submit = executor.submit(runnable);
}
executor.awaitTermination(1, TimeUnit.HOURS);
}
public static void main(String[] args) throws InterruptedException
{
if (args.length < 3)
{
System.err.println("Usage: VMTest threadCount taskDef size");
System.err.println("threadCount: Number 1..n");
System.err.println("taskDef: int string array");
System.err.println("size: size of memory allocation for array, ");
System.exit(-1);
}
new VMTest().doIt(args);
}
}
source d'informationauteur ReneS
Vous devez vous connecter pour publier un commentaire.
Je ne vois rien de mal avec votre code.
Toutefois, malheureusement, vous ne pouvez pas spécifier l'affinité du processeur en Java. Donc, c'est en fait à gauche jusqu'à l'OS, pas de la JVM. Il est tout au sujet de la façon dont votre système d'exploitation gère les threads.
Vous pourriez diviser votre threads Java dans des processus séparés et les envelopper dans du code natif, de mettre un processus par cœur. Ce n'est, bien sûr, de compliquer la communication, comme il sera inter-processus plutôt qu'inter-thread. De toute façon, c'est comment populaire de la grille de calcul des applications comme boink travail.
Sinon, vous êtes à la merci de l'OS pour planifier les threads.
Je suppose que c'est inhérent à la JVM/OS et pas nécessairement de votre code. Vérifier les différents JVM de réglage des performances de docs de Soleil, par exemple, http://ch.sun.com/sunnews/events/2009/apr/adworkshop/pdf/5-1-Java-Performance.pdf qui suggère l'utilisation de
numactl
sur Linux pour définir l'affinité.Bonne chance!
Apparemment, votre VM est en cours d'exécution dans les soi-disant "client", où tous les threads Java sont mappés sur un système d'exploitation natif fil et, par conséquent, sont gérés par un seul cœur de PROCESSEUR. Essayez d'appeler la JVM avec
-server
interrupteur, cela devrait corriger le problème.Si vous obtenez une:
Error: no 'server' JVM
trouvé, vous devrez copier leserver
directory à partir d'un JDK estjre\bin
répertoire JREbin
.uname-a
2.6.18-194.11.4.el5 #1 SMP tue Sep 21 05:04:09 HAE 2010 x86_64 x86_64 x86_64 GNU/Linux
Intel(R) Xeon(R) CPU E5530 @ 2.40 GHz
http://browse.geekbench.ca/geekbench2/view/182101
Java 1.6.0_20-b02
16cores, le programme a consommé de cpu à 100%, comme indiqué par la commande vmstat
Il est intéressant de noter que je suis venu à cet article parce que je suis se doutant de ma demande est de ne pas utiliser tous les cœurs que l'utilisation cpu n'augmente jamais, mais le temps de réponse se détériore
J'ai remarqué que même sur C qu'une boucle a souvent des problèmes comme ça. Vous verrez aussi d'assez grandes différences selon les OS.
Selon l'outil que vous utilisez, il ne peut pas signaler le CPU utilisé par certains services de base.
Java a tendance à être assez sympathique. Vous pouvez essayer la même chose sous linux, mais de définir la priorité du processus de certains aspects négatifs de nombre et de voir comment il agit.
Définissant les priorités des threads à l'intérieur de l'app peut aider un peu trop si votre jvm n'est pas à l'aide de fils verts.
Beaucoup de variables.