4 cœurs, 2 caches ?

Le
Lucas Levrel
Bonjour,

Soit une station équipée d'un processeur Xeon E5440. La bête a 4 cœurs et,
dans les docs d'Intel, 12 MB de cache parfois présentés comme 2×6 MB.

Je lance un programme qui exécute plusieurs threads effectuant la même
tâche (sur une même quantité de données différentes). Quand il y a 4
threads, ils finissent à peu près en même temps. Quand il y en a 3, il y
en a toujours un qui finit nettement avant les autres.

Si l'on ajoute le fait que /proc/cpuinfo annonce 6 MB de cache pour chaque
cœur, ça m'amène à croire qu'il y a deux blocs de 6 MB cache, chacun
partagé par deux cœurs. Mes questions sont : comment savoir quels cœurs
sont « appariés » et comment fixer un thread sur un cœur donné (l'idée
étant de ne lancer que deux threads, sur des cœurs non appariés) ? Ou
est-ce qu'en lançant seulement deux threads le système va automatiquement
les mettre sur des cœurs non appariés (ce qui est le plus performant) ?

Le code est en C++ et utilise la bibliothèque TBB (threading building
blocks) d'Intel, mais je peux passer à une autre (pthread ?) si besoin.

/proc/cpuinfo, je ne répète pas les lignes qui sont identiques pour tous
les cœurs :

processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Xeon(R) CPU E5440 @ 2.83GHz
stepping : 6
cpu MHz : 2826.258
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 0
cpu cores : 4
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca
cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx
lm constant_tsc arch_perfmon pebs bts rep_good pni monitor ds_cpl vmx est
tm2 ssse3 cx16 xtpr dca sse4_1 lahf_lm
bogomips : 5656.61
clflush size : 64
cache_alignment : 64
address sizes : 38 bits physical, 48 bits virtual
power management:

processor : 1
core id : 2
bogomips : 5652.60

processor : 2
core id : 1
bogomips : 5652.63

processor : 3
core id : 3
bogomips : 5652.57

Crosspost dans fcolc et fclc++, suivi à discrétion. (Est-ce que fco.unix
serait plus approprié que fcolc ?)

Merci pour votre aide.
--
LL
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Yliur
Le #23012111
Le Tue, 11 Jan 2011 11:51:20 +0100
Lucas Levrel
Bonjour,

Soit une station équipée d'un processeur Xeon E5440. La bête a 4
cœurs et, dans les docs d'Intel, 12 MB de cache parfois présentés
comme 2×6 MB.

Je lance un programme qui exécute plusieurs threads effectuant la
même tâche (sur une même quantité de données différentes). Quand il y
a 4 threads, ils finissent à peu près en même temps. Quand il y en a
3, il y en a toujours un qui finit nettement avant les autres.

Si l'on ajoute le fait que /proc/cpuinfo annonce 6 MB de cache pour
chaque cœur, ça m'amène à croire qu'il y a deux blocs de 6 MB cache,
chacun partagé par deux cœurs.



Il n'y aurait pas que deux coeurs réels, vus comme 4 coeurs virtuels ?
Intel appelle ça Hyperthreading, mais je ne sais pas si c'est le cas
sur ce modèle de processeurs.


Mes questions sont : comment savoir
quels cœurs sont « appariés »



Ça je ne sais pas, ni même si on peut le savoir.


et comment fixer un thread sur un cœur
donné (l'idée étant de ne lancer que deux threads, sur des cœurs non
appariés) ? Ou est-ce qu'en lançant seulement deux threads le système
va automatiquement les mettre sur des cœurs non appariés (ce qui est
le plus performant) ?



C'est son travail (au système). Inquiète-toi seulement s'il ne le fait
pas.
Lucas Levrel
Le #23013031
Le 11 janvier 2011, Yliur a écrit :

Il n'y aurait pas que deux coeurs réels, vus comme 4 coeurs virtuels ?
Intel appelle ça Hyperthreading, mais je ne sais pas si c'est le cas
sur ce modèle de processeurs.



Bonne idée. Sur la page
http://ark.intel.com/Product.aspx?id3082&processorå440&spec-codes=SLANS,SLBBJ
ils disent « # of cores : 4, # of threads : 4, Hyperthreading : No », donc
c'est bien 4 cœurs réels.

Mes questions sont : comment savoir quels cœurs sont « appariés »



Ça je ne sais pas, ni même si on peut le savoir.



À propos : dans le cpuinfo on voit que processor n'est pas égal à core
id. Est-ce que processor est créé dynamiquement au boot et peut être
associé différemment aux core id au prochain boot ? (À la manière des
/dev/sdX qui peuvent être associés à différents disques, seuls les
/dev/disk/by-uuid/XXX étant stables.)

C'est son travail (au système). Inquiète-toi seulement s'il ne le fait
pas.



OK.

--
LL
Alain Ketterlin
Le #23013251
Lucas Levrel
Soit une station équipée d'un processeur Xeon E5440. La bê te a 4 cœurs
et, dans les docs d'Intel, 12 MB de cache parfois présentés com me 2×6
MB.



Oui, il me semble que ce sont en fait deux dual-core assemblés sur la
même puce.

Je lance un programme qui exécute plusieurs threads effectuant la m ême
tâche (sur une même quantité de données différen tes). Quand il y a 4
threads, ils finissent à peu près en même temps. Quand il y en a 3, il
y en a toujours un qui finit nettement avant les autres.



Et quand il n'y en a que 2 ? Le temps total est-il plus faible ?

Si l'on ajoute le fait que /proc/cpuinfo annonce 6 MB de cache pour
chaque cœur, ça m'amène à croire qu'il y a deux blocs de 6 MB cache,
chacun partagé par deux cœurs. Mes questions sont : comment sav oir
quels cœurs sont « appariés » et comment fi xer un thread sur un cœur
donné (l'idée étant de ne lancer que deux threads, sur des cœurs non
appariés) ?



Je ne pense pas qu'on puisse déterminer l'appariement, mais je serais
surpris qu'il se passe des choses subtiles.

Pour l'affinité (d'un thread/process sur un cpu), tu peux essayer
la commande taskset, voire sched_setaffinity/pthread_setaffinity_np, à
condition d'avoir les infos.

Ou est-ce qu'en lançant seulement deux threads le système
va automatiquement les mettre sur des cœurs non appariés (ce qu i est
le plus performant) ?



Si quelqu'un connaît la réponse...

Le code est en C++ et utilise la bibliothèque TBB (threading building
blocks) d'Intel, mais je peux passer à une autre (pthread ?) si
besoin.



Il me semble que TBB déconseille de jouer directement avec les threads
sous-jacents. Selon la complexité de ton programme, tu risques de perd re
plus à te passer de TBB que de jouer avec les affinités. Si ce n' est pas
le cas, c'est une bonne idée de jongler avec les paramètres, mais c'est
un sport différent.

-- Alain.
Lucas Levrel
Le #23014871
Le 12 janvier 2011, Alain Ketterlin a écrit :

Pour l'affinité (d'un thread/process sur un cpu), tu peux essayer
la commande taskset, voire sched_setaffinity/pthread_setaffinity_np, à
condition d'avoir les infos.



Je viens de trouver ça dans le manuel d'Intel Math Kernel Library, c'est
un peu abscons mais ça ressemble drôlement à mon problème :
-:-:-
Consider the following performance issue:

* The system has two sockets with two cores each, for a total of four
cores (CPUs)
* The two -thread parallel application that calls the Intel(R) Math
Kernel Library (Intel(R) MKL) FFT happens to run faster than in four
threads, but the performance in two threads is very unstable

The following code example shows how to resolve this issue by setting an
affinity mask by operating system means using the Intel(R) compiler. The
code calls the system function sched_setaffinity to bind the threads to
the cores on different sockets.
(snip)
cpu_set_t new_mask;
cpu_set_t was_mask;
int tid = omp_get_thread_num();

CPU_ZERO(&new_mask);

// 2 packages x 2 cores/pkg x 1 threads/core (4 total cores)
CPU_SET(tid==0 ? 0 : 2, &new_mask);

if (sched_getaffinity(0, sizeof(was_mask), &was_mask) == -1) {
printf("Error: sched_getaffinity(%d, sizeof(was_mask), &was_mask)n", tid);
}
if (sched_setaffinity(0, sizeof(new_mask), &new_mask) == -1) {
printf("Error: sched_setaffinity(%d, sizeof(new_mask), &new_mask)n", tid);
}
-:-:-
http://software.intel.com/sites/products/documentation/hpc/composerxe/en-us/mklxe/mkl_userguide_lnx/MKL_UG_managing_performance/Managing_Multi-core_Performance.htm

Ils ont l'air de considérer comme évident que les CPU 0 et 2 sont sur des
sockets différents... Pourtant sur une machine avec deux quad-cores,
/proc/cpuinfo contient :
processor : 0
physical id : 0
core id : 0
apicid : 0

processor : 1
physical id : 1
core id : 0
apicid : 4

processor : 2
physical id : 0
core id : 1
apicid : 1

processor : 3
physical id : 1
core id : 1
apicid : 5

processor : 4
physical id : 0
core id : 2
apicid : 2

processor : 5
physical id : 1
core id : 2
apicid : 6

processor : 6
physical id : 0
core id : 3
apicid : 3

processor : 7
physical id : 1
core id : 3
apicid : 7

0, 2, 4 et 6 sont sur la même puce... (je suppose que ce n'est pas apicid
qui est utilisé par sched.h, car l'autre machine n'a pas ce champ dans son
cpuinfo)

--
LL
Alain Ketterlin
Le #23015061
Lucas Levrel
Pour l'affinité (d'un thread/process sur un cpu), tu peux essayer
la commande taskset, voire sched_setaffinity/pthread_setaffinity_np, Ã  
condition d'avoir les infos.



Je viens de trouver ça dans le manuel d'Intel Math Kernel Library,
c'est un peu abscons mais ça ressemble drôlement à mon pro blème :


[...]
int tid = omp_get_thread_num();



Fais gaffe, ce code est manifestement pour un programme OpenMP
(omp_get_thread_num renvoie un numéro entre 0 et N-1, où N est le nombre
de threads du pool courant). Si tu utilises TBB, je crois que la classe
thread a un équivalent.

Pour la numérotation, je ne sais pas.

-- Alain.
Lucas Levrel
Le #23017011
Le 12 janvier 2011, Alain Ketterlin a écrit :

Fais gaffe, ce code est manifestement pour un programme OpenMP
(omp_get_thread_num renvoie un numéro entre 0 et N-1, où N est le nombre
de threads du pool courant). Si tu utilises TBB, je crois que la classe
thread a un équivalent.



Oui, je ne vais pas copier-coller ce code :-) Mais la problématique me
semble similaire à la mienne, surtout sachant ce que tu m'as dit sur mon
quad-core qui est en fait un double dual-core.

Merci de t'être penché sur mon problème.
--
LL
Alain Ketterlin
Le #23017691
Lucas Levrel
[...]
Si l'on ajoute le fait que /proc/cpuinfo annonce 6 MB de cache pour
chaque cœur, ça m'amène à croire qu'il y a deux blocs de 6 MB cache,
chacun partagé par deux cœurs. Mes questions sont : comment sav oir
quels cœurs sont « appariés » et comment fi xer un thread sur un cœur
donné (l'idée étant de ne lancer que deux threads, sur des cœurs non
appariés) ?



Ca y est, ça m'est revenu. On peut obtenir la topologie avec les outils
de hwloc, à http://www.open-mpi.org/projects/hwloc/

-- Alain.
Lucas Levrel
Le #23018081
Le 13 janvier 2011, Alain Ketterlin a écrit :

Ca y est, ça m'est revenu. On peut obtenir la topologie avec les outils
de hwloc, à http://www.open-mpi.org/projects/hwloc/



Je vais regarder ça, merci.

--
LL
Publicité
Poster une réponse
Anonyme