J'utilise Ubuntu sur une machine dotée d'un processeur à quatre cœurs. J'ai écrit un code Java de test qui génère un nombre donné de processus qui incrémentent simplement une variable volatile pour un nombre donné d'itérations lors de l'exécution.
Je m'attendrais à ce que le temps de fonctionnement n'augmente pas de manière significative tant que le nombre de threads est inférieur ou égal au nombre de cœurs, c'est-à-dire 4. En fait, ce sont les temps que j'obtiens en utilisant le "temps réel" de l'UNIX time
commandement :
1 fil : 1.005s
2 fils : 1.018s
3 fils : 1.528s
4 fils : 1.982s
5 fils : 2.479s
6 fils : 2.934s
7 fils : 3.356s
8 fils : 3.793s
Cela montre que l'ajout d'un thread supplémentaire n'augmente pas le temps comme prévu, mais le temps fait augmenter avec 3 et 4 fils.
Au début, j'ai pensé que cela pouvait être dû au fait que le système d'exploitation empêchait la JVM d'utiliser tous les cœurs, mais j'ai lancé l'opération suivante top
Il a clairement montré qu'avec 3 threads, 3 cœurs fonctionnaient à ~100%, et qu'avec 4 threads, 4 cœurs étaient au maximum.
Ma question est la suivante : pourquoi le code qui s'exécute sur 3/4 CPU n'a pas à peu près la même vitesse que lorsqu'il s'exécute sur 1/2 CPU ? Parce qu'il est fonctionnant en parallèle sur tous les cœurs.
Voici ma méthode principale à titre de référence :
class Example implements Runnable {
// using this so the compiler does not optimise the computation away
volatile int temp;
void delay(int arg) {
for (int i = 0; i < arg; i++) {
for (int j = 0; j < 1000000; j++) {
this.temp += i + j;
}
}
}
int arg;
int result;
Example(int arg) {
this.arg = arg;
}
public void run() {
delay(arg);
result = 42;
}
public static void main(String args[]) {
// Get the number of threads (the command line arg)
int numThreads = 1;
if (args.length > 0) {
try {
numThreads = Integer.parseInt(args[0]);
} catch (NumberFormatException nfe) {
System.out.println("First arg must be the number of threads!");
}
}
// Start up the threads
Thread[] threadList = new Thread[numThreads];
Example[] exampleList = new Example[numThreads];
for (int i = 0; i < numThreads; i++) {
exampleList[i] = new Example(1000);
threadList[i] = new Thread(exampleList[i]);
threadList[i].start();
}
// wait for the threads to finish
for (int i = 0; i < numThreads; i++) {
try {
threadList[i].join();
System.out.println("Joined with thread, ret=" + exampleList[i].result);
} catch (InterruptedException ie) {
System.out.println("Caught " + ie);
}
}
}