Programmation parallèle et HyperThreading : les limites…

Je suis en train de bouquiner cette merveille de Joe Duffy :

http://www.amazon.com/Concurrent-Programming-Windows-CONCURRENT-PROGRAMMING/dp/B002HLS6QK

Concurrent Programming on Windows [CONCURRENT PROGRAMMING ON WIND]

Que ceux qui aiment en avoir pour leur argent courent l’acheter : c’est du lourd, dans tous les sens du terme… 950 pages, mais surtout une mine d’information sur ce qui se passe derrière les mécanismes de threading : comment Windows gère, découpe, affecte les tranches et les priorités, quels sont les mécanismes de verrou et comment ils fonctionnent, comment ils peuvent être mis en oeuvre au niveau du hardware, etc. Génial…

La raison pour laquelle je parle de ce livre est qu’il m’a permis de comprendre en détail ce qui se passait sur la parallélisation de calculs intensifs avec l’HyperThreading.

Pour situer le contexte : lors de mes premiers tests sur la parallélisation, j’ai souhaité voir la performance des BlockingCollection et j’ai réalisé le petit programme ci-dessous :

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Collections.Concurrent;

namespace TestParallelisme
{
    class Program
    {
        static void Main(string[] args)
        {
            List<int> Entiers = new List<int>();
            for (int i = 1000000; i < 1200000; i++)
                Entiers.Add(i);

            List<int> PremiersStandard = new List<int>();
            Stopwatch Chrono = Stopwatch.StartNew();
            foreach (int Entier in Entiers)
                if (EstPremier(Entier))
                    PremiersStandard.Add(Entier);
            Console.WriteLine("{0} premiers trouvés en {1}", PremiersStandard.Count, Chrono.Elapsed);

            BlockingCollection<int> PremiersParallel = new BlockingCollection<int>();
            Chrono = Stopwatch.StartNew();
            Parallel.ForEach(Entiers, i => { if (EstPremier(i)) PremiersParallel.Add(i); });
            Console.WriteLine("{0} premiers trouvés en {1}", PremiersParallel.Count, Chrono.Elapsed);

        }

        private static bool EstPremier(int Entier)
        {
            for (int i = 2; i < Entier - 1; i++)
                if (Entier % i == 0)
                    return false;
            return true;
        }
    }
}

Vu que la machine de test est un bi-processeur Quad-Core avec l’HyperThreading activé, je disposais de 16 voies, et le calcul parallélise évidemment très bien :

image

Mais en termes de performance, on n’est pas sur un rapport de 16, mais très proche de 8 :

image

Ceci m’a vite fait penser que l’HyperThreading n’était pas fait pour exécuter en parallèle du code intensif, mais bien pour accélérer le traitement en gardant des contextes d’exécution dédoublés, tout en partageant l’unité de calcul.

Si on désactive l’HT dans le BIOS, on voit qu’on ne dispose plus que de 8 voies :

image

Mais les performances n’ont quasiment pas bougé :

image

Voila qui confirmait que l’HyperThreading n’accélérait les traitements que lorsqu’ils ne sont pas intensifs du point de vue du CPU. J’avais enfin la justification mesurable des articles sur les blogs Maya qui expliquait qu’il valait mieux désactiver l’HT. Effectivement, pour des opérations de rendu 3D très gourmandes en CPU, l’HT n’apporte rien. Il peut effectivement permettre d’exécuter en parallèle des threads avec peu de calcul, mais de toute façon, le gain ne sera que parce qu’il n’y a pas de perte de temps pour le rechargement du contexte.

Avoir une justification quantifiée est sympa, mais le mieux est encore d’avoir l’explication précise de pourquoi ça fonctionne comme ça… mais ça, c’est le bouquin de Joe Duffy qui vous le dira !

Oui, je sais, vous aimeriez bien avoir la réponse, mais ce bouquin est tellement bien fait que je ne me permettrai pas d’expliquer avec mes mots à moi, qui reflèteraient le fait que je ne suis pas encore 100% à l’aise avec ces concepts, ce qui est très bien amené dans le livre. A vos libraires, donc…

Et en cadeau-bonus : un chapitre gratuit !

About JP Gouigoux

Jean-Philippe Gouigoux est Architecte Logiciel, MVP Connected Systems Developer. Il intervient régulièrement à l'Université de Bretagne Sud ainsi qu'à l'Agile Tour. Plus de détails sur la page "Curriculum Vitae" de ce blog.
This entry was posted in Parallélisation. Bookmark the permalink.

2 Responses to Programmation parallèle et HyperThreading : les limites…

  1. gallier2 says:

    En fait, la réponse est assez simple. L’hyper-thread dédouble le “front-end” (décodeur, distributeur) du processeur, mais laisse le “back-end” (les ressources d’excécution) au même niveau. C’est-à-dire qu’un processeur, dimensionné pour l’exécution d’un processus, partage cette ressource entre 2 processus. Si ces processus sont capables de fournir le code et les données assez rapidement, il y a contention et les 2 threads se battent pour les ressources. Par contre, si un des processus se trouvait dans un état où il doit attendre le code ou les données, l’autre processus peut utiliser les ressources pendant ce temps. Ce qui veut dire, que l’hyperthread est intéressant lorsque les processus ont beaucoup de défauts de cache comme dans des grandes bases de données par exemple ou sur le traitement de flux séquentiels, comme dans des encodeurs vidéo.
    Donc dans votre exemple comme la taille des données est relativement faible les caches sont utilisés idéalement et les 2 threads fournissent les données à un rythme qui dépassent la capacité d’exécution.
    Les chiffres officiels sont d’ailleurs de l’ordre -5% à +30% de gain pour l’HT.
    Personnellement je préfère l’approche d’AMD avec sa gamme bulldozer, qui ont doublé le back-end (entier) et partagé le front-end et le back-end virgule flottante. Cela donne un exécution parallèle plus régulière qu’avec l’HT (quant à l’évaluation de la qualité des Bulldozer ne pas se laisser leurrer par les innombrables critiques immatures qu’on trouve sur Internet, elles ne sont pas objectives, mais ça c’est un autre sujet).

    • JP Gouigoux says:

      Un grand merci pour ce commentaire : c’est aussi bien expliqué que dans le livre… mais en français, ce qui réjouira les allergiques aux bouquins en anglais 🙂

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha Captcha Reload