Le code Java simple ci-joint doit charger tout le cpu core disponible lors du démarrage avec les bons paramètres. Ainsi, par exemple, vous commencez avecPourquoi ce code Java n'utilise-t-il pas tous les cœurs de processeur?
java VMTest 8 int 0
et il va commencer 8 fils qui ne font rien d'autre que boucle et en ajoutant 2 à un nombre entier. Quelque chose qui s'exécute dans les registres et n'attribue même pas de nouvelle mémoire. Le problème auquel nous sommes confrontés maintenant, c'est que nous ne disposons pas d'une machine 24 cœurs (AMD 2 sockets avec 12 cœurs chacun), lors de l'exécution de ce simple programme (avec 24 threads bien sûr). Des choses similaires se produisent avec 2 programmes de 12 threads ou de plus petites machines.
Donc, notre soupçon est que la JVM (Sun JDK 6u20 sous Linux x64) ne se met pas bien à l'échelle.
Quelqu'un at-il vu des choses similaires ou a-t-il la capacité de les faire fonctionner et de signaler s'il fonctionne bien sur sa machine (> = 8 coeurs seulement s'il vous plaît)? Des idées?
J'ai essayé sur Amazon EC2 avec 8 cœurs aussi, mais la machine virtuelle semble fonctionner différemment d'une vraie boîte, donc le chargement se comporte de manière 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);
}
}
Informations supplémentaires. Je viens de découvrir que la version 64 bits du JDK charge mieux les cœurs (environ 90%) que la version 32 bits (environ 45%). Ce qui est étrange, car le système d'exploitation et le cpu AMD supportent 32bit et je n'exécute aucune opération de mémoire pendant ce test. – ReneS
Juste pour comprendre - pourquoi n'utilisez-vous pas la méthode invokeAll (..)? Et pourquoi n'utilisez-vous pas les callables, autant que je sache, runnable ne fait pas partie de java.concurrent? – InsertNickHere
Vous devez également surveiller les autres processus en cours d'exécution. Avez-vous fait une course "propre", sans autres progamms/processus prenant le temps de cpu? – InsertNickHere