Je suis actuellement en train de paralléliser un programme en utilisant openmp sur un phenom2 à 4 cœurs. Cependant, j'ai remarqué que ma parallélisation ne fait rien pour les performances. Naturellement, j'ai supposé que j'avais manqué quelque chose (falsesharing, sérialisation par les verrous, ...), mais je n'ai rien trouvé de tel. De plus, d'après l'utilisation du CPU, il semble que le programme ait été exécuté sur un seul cœur. D'après ce que j'ai trouvé sched_getcpu()
devrait me donner l'Id du noyau sur lequel le thread exécutant l'appel est actuellement planifié. J'ai donc écrit le programme de test suivant :
#include <iostream>
#include <sstream>
#include <omp.h>
#include <utmpx.h>
#include <random>
int main(){
#pragma omp parallel
{
std::default_random_engine rand;
int num = 0;
#pragma omp for
for(size_t i = 0; i < 1000000000; ++i) num += rand();
auto cpu = sched_getcpu();
std::ostringstream os;
os<<"\nThread "<<omp_get_thread_num()<<" on cpu "<<sched_getcpu()<<std::endl;
std::cout<<os.str()<<std::flush;
std::cout<<num;
}
}
Sur ma machine, cela donne le résultat suivant (les nombres aléatoires varient bien sûr) :
Thread 2 on cpu 0 num 127392776
Thread 0 on cpu 0 num 1980891664
Thread 3 on cpu 0 num 431821313
Thread 1 on cpu 0 num -1976497224
A partir de là, je suppose que tous les threads s'exécutent sur le même noyau (celui qui a l'id 0). Pour être plus sûr, j'ai également essayé l'approche de cette réponse . Les résultats ont été les mêmes. De plus, en utilisant #pragma omp parallel num_threads(1)
n'a pas rendu l'exécution plus lente (légèrement plus rapide en fait), ce qui donne de la crédibilité à la théorie selon laquelle tous les threads utilisent le même cpu, cependant le fait que le cpu soit toujours affiché comme 0
me rend un peu suspicieux. De plus, j'ai vérifié GOMP_CPU_AFFINITY
qui n'était pas défini initialement, j'ai donc essayé de le définir sur 0 1 2 3
ce qui devrait lier chaque fil à un noyau différent d'après ce que je comprends. Cependant, cela n'a pas fait de différence.
Comme je développe sur un système Windows, j'utilise linux en virtualbox pour mon développement. J'ai donc pensé que le système virtuel ne pouvait peut-être pas accéder à tous les cœurs. Cependant, en vérifiant les paramètres de virtualbox, j'ai constaté que la machine virtuelle devait avoir accès aux 4 cœurs et l'exécution de mon programme de test 4 fois en même temps semble utiliser les 4 cœurs à en juger par l'utilisation du processeur (et le fait que le système devenait très peu réactif).
Ma question est donc de savoir ce qui se passe exactement ici. Plus précisément : Ma déduction selon laquelle tous les threads utilisent le même noyau est-elle correcte ? Si c'est le cas, quelles pourraient être les raisons de ce comportement ?