Tout dépend de ce que tu appelles ordonnancement. Les threads noyaux sont ordonnancés par l'OS, sauf si tu lui demandes gentiment de faire autrement (en passant par les cpusets, en l'occurrence).
Les performances (au moins dans le cas du calcul scientifique) sont clairement meilleures lorsque les threads sont fixés sur un processeur, tout simplement parce qu'un changement de contexte sur un même processeur peut se faire à un coût relativement réduit, alors que migrer un thread d'un processeur à un autre implique la recopie (et donc très certainement de l'utilisation du bus mémoire) pour recopier l'intégralité du contexte d'exécution d'un thread.
D'autre part, je parle d'ordonnancement de threads utilisateur, et pas des threads noyaux en tant que tels (par définition, c'est le noyau qui décide de la préemption ou pas), si ce n'est pour cette histoire de fixer les threads sur un proc donné.
« Bref, si tu as une machine linux avec qq centaines de processeurs, je laisserais faire l'OS. »
Honnêtement, heureusement que les gens ne t'écoutent pas sur les centres de calcul :-)
Migration de thread d'un proc à l'autre => transfert du contexte (comme dit précédemment), mais aussi pollution des caches, et en cas de modèle NUMA, accès distant à la RAM, ou alors overhead dû à la nécessité de recopier les pages mémoire vers la nouvelle mémoire locale ...
« Je n'imagine pas faire du scheduling à la main pour des raisons de "thoughput" (de bande passante), »
Si je fais de l'ordonnancement statique, c'est entre autres parce que la façon dont mes threads utilisateur sont ordonancés, j'ai une pollution plus ou moins grande des caches entre les processeurs (par exemple, l'ensemble de données sur lequel je bosse est subdivisé en sous-ensembles plus élémentaires et indépendants, mais suivant la façon dont je fais ma découpe, les différents threads vont potentiellement écrire dans les mêmes lignes de cache, et du coup un gros traffic va être mis en oeuvre pour régler la cohérence, ce qui n'arrive pas si je fais travailler mes threads sur des portions de données qui n'entrent pas en conflit dans les caches). Comme j'ai des E/S quasi-nulles, c'est le fait de devoir sortir de mes caches qui est le facteur le plus limitant (et quand tu multiplies des matrices, du genre (5000,128)x(128,5000), ça prend un certain temps. Pour te donner un ordre d'idée, en changeant ma façon d'ordonnancer les threads, je suis passé de 8-10 GFLOPS sur 4 coeurs itanium 2 à 18-22 GFLOPS (sur les 25,2 théoriques).
[^] # Re: Le fortran
Posté par lasher . En réponse au journal Qu'est-ce qu'un langage sécurisé ?. Évalué à 3.
Les performances (au moins dans le cas du calcul scientifique) sont clairement meilleures lorsque les threads sont fixés sur un processeur, tout simplement parce qu'un changement de contexte sur un même processeur peut se faire à un coût relativement réduit, alors que migrer un thread d'un processeur à un autre implique la recopie (et donc très certainement de l'utilisation du bus mémoire) pour recopier l'intégralité du contexte d'exécution d'un thread.
D'autre part, je parle d'ordonnancement de threads utilisateur, et pas des threads noyaux en tant que tels (par définition, c'est le noyau qui décide de la préemption ou pas), si ce n'est pour cette histoire de fixer les threads sur un proc donné.
« Bref, si tu as une machine linux avec qq centaines de processeurs, je laisserais faire l'OS. »
Honnêtement, heureusement que les gens ne t'écoutent pas sur les centres de calcul :-)
Migration de thread d'un proc à l'autre => transfert du contexte (comme dit précédemment), mais aussi pollution des caches, et en cas de modèle NUMA, accès distant à la RAM, ou alors overhead dû à la nécessité de recopier les pages mémoire vers la nouvelle mémoire locale ...
« Je n'imagine pas faire du scheduling à la main pour des raisons de "thoughput" (de bande passante), »
Si je fais de l'ordonnancement statique, c'est entre autres parce que la façon dont mes threads utilisateur sont ordonancés, j'ai une pollution plus ou moins grande des caches entre les processeurs (par exemple, l'ensemble de données sur lequel je bosse est subdivisé en sous-ensembles plus élémentaires et indépendants, mais suivant la façon dont je fais ma découpe, les différents threads vont potentiellement écrire dans les mêmes lignes de cache, et du coup un gros traffic va être mis en oeuvre pour régler la cohérence, ce qui n'arrive pas si je fais travailler mes threads sur des portions de données qui n'entrent pas en conflit dans les caches). Comme j'ai des E/S quasi-nulles, c'est le fait de devoir sortir de mes caches qui est le facteur le plus limitant (et quand tu multiplies des matrices, du genre (5000,128)x(128,5000), ça prend un certain temps. Pour te donner un ordre d'idée, en changeant ma façon d'ordonnancer les threads, je suis passé de 8-10 GFLOPS sur 4 coeurs itanium 2 à 18-22 GFLOPS (sur les 25,2 théoriques).