Dans cette session présentée le 21 avril 2010 à Paris dans les locaux d'OCTO Technology. Vous découvrirez les règles essentielles et les principaux patterns parallèles qui vous aideront à écrire en C# 4.0 des applications parallèles plus évolutives et plus faciles à maintenir pour retrouver le Free Lunch
10. Trouver la concurrenceSolution séquentielle Dépiler un nom de fichier WM_TIMER Sélectionner un répertoire Charger une image Structure de pile partagée Charger tous les noms d’images dans le répertoire et ses sous répertoires Normaliser l’image Twister l’image Insérer dans le contrôle graphique Empiler les noms de fichiers sélectionnés Convertir l’image en une vignette
11. Etape 2Décomposition et granularité Votre décomposition en tâches doit tenir compte de leur granularité et de leur surcoût Cœur 0 Cœur 1 Cœur 2 Cœur 3 Cœur 1 Cœur 2 Cœur 0 Cœur 3 tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche Configuration 2 Quelle est la meilleure configuration ? Configuration 1 surcoût charge
12. Etape 2Décomposition et répartition de charge Votre groupement de tâches doit tenir compte de leur charge Cœur 1 tâche Cœur 2 Cœur 0 Cœur 3 Cœur 1 Cœur 2 Cœur 0 Cœur 3 tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche tâche Configuration 2 Quelle est la meilleure configuration ? Configuration 1 surcoût charge
13. Etape 2Evaluer votre design Flexibilité Préférer l’abstraction pour faciliter l’adaptation à différents scénarios d’exécution Nombre de cœurs sollicités Partitionnement des données Efficacité Le temps dépensé à gérer le parallélisme vs le temps gagné à tirer parti des cœurs Amélioration des performances en fonction du nombre de processeurs Simplicité Le code peut être facilement diagnostiqué La solution technique choisie est facile à maintenir
14. Etape 3 Choisir un algorithme en fonction de votre stratégie
23. Les variables locales utilisées ensemble dans une fermeture sont probablement capturées dans les champs d'instance, et ainsi, d'après le premier commentaire ci-dessus, sont également proches en mémoireMémoire
25. Etape 3Décomposition géométrique for (int i = 0; i < size; i++) { Parallel.For(0, size, j => { inttemp = 0; for (int k = 0; k < size; k++) { temp += m1[i, k] + m2[k, j]; } result[i, j] = temp; }); }
26.
27. Etape 3Récursivité sur des données staticvoidWalk<T>(Tree<T> root, Action<T> Action) { if (root == null) return; var t1 = Task.Factory.StartNew(() => action(root.Data)); var t2 = Task.Factory.StartNew(() => Walk(root.Left, action)); var t3 = Task.Factory.StartNew(() => Walk(root.Rigth, action)); Task.WaitAll(t1, t2, t3); }
31. lecture seule ou lecture/écrituresous opération 1 sous opération 2 sous opération 3 sous opération 4 sous opération 4 sous opération 1 sous opération 2 Paralléliser des opérations décomposables sous opération 3
32.
33. Etape 3Diviser pour régner staticvoidQuickSort<T>(T[] data, intfromInclusive, inttoExclusive) where T : IComparable<T> { if (toExclusive - fromInclusive <= THRESHOLD) { InsertionSort(data, fromInclusive, toExclusive); } else { intpivotPos = Partition(data, fromInclusive, toExclusive); if (toExclusive - fromInclusive <= PARALLEL_THRESHOLD) { // NOTE: PARALLEL_THRESHOLD ischosen to begreaterthan THRESHOLD. QuickSort(data, fromInclusive, pivotPos); QuickSort(data, pivotPos, toExclusive); } elseParallel.Invoke( () => QuickSort(data, fromInclusive, pivotPos), () => QuickSort(data, pivotPos, toExclusive)); } }
34.
35. inégales – pipeline non-linéaireChaîne de montage automobile
36. Etape 3Algorithmes flux de données Coordination orientée événements Traitement d’une dépêche sur un desk journalistique …
37. Etape 3Pipeline var input = new BlockingCollection<string>(); var readLines = Task.Factory.StartNew(() => { try { foreach(var line in File.ReadAllLines(@"input.txt")) input.Add(line); } finally { input.CompleteAdding(); } }); var writeLines = Task.Factory.StartNew(() => { File.WriteAllLines(@"output.txt", input.GetConsumingEnumerable()); }); Task.WaitAll(readLines, writeLines);
39. Etape 4Choisir un pattern de structures de programme Après avoir sélectionné votre algorithme parallèle, il faut maintenant le supporter dans votre programme Structures de programme SPMD Master/Worker Boucle parallèle Fork/Join
40. Etape 4Les Patterns de structures de programme SPMD, Master/Worker, Boucle parallèle et Fork/Join partagent les mêmes idiomes Partitionner Exécuter Fusionner
41. Etape 4Fork / Join var tasks = new Task[3]; tasks[0] = new Task(() => ComputeMean()); tasks[1] = new Task(() => ComputeMedian()); tasks[2] = new Task(() => ComputeMode()); foreach(Task t in tasks) t.Start(); Task.WaitAll(tasks); Parallel.Invoke( () => ComputeMean(), () => ComputeMedian(), () => ComputeMode() );
42. Etape 4Boucle parallèle Parallel.ForEach(stack, bitmap => _imagesStack.Push(ProcessBitmap(bitmap))); var query = from bitmap in stack.AsParallel() select ProcessBitmap(bitmap); query.ForAll(image => _imagesStack.Push(image));
45. Structures de programme parallèleSolution parallèle WM_TIMER Collection des noms de fichiers Sélectionner un répertoire Pile partagée concurrente Charger une image Charger tous les noms d’images dans le répertoire et ses sous répertoires Dépiler une vignette Normaliser l’image Insérer dans le contrôle graphique Twister l’image Empiler les noms de fichiers sélectionnés Convertir l’image en une vignette
49. ConclusionQuelques suggestions pour l’implémentation Préférer les nouveaux outils de haut niveau d’abstraction Privilégier les solutions simples à maintenir La granularité fine est souvent synonyme de complexité Utiliser systématiquement des librairies thread-safe Fiabilité == Gain de temps Ne jamais présumer d’un ordre d’exécution La justesse du code est à ce prix
50. ConclusionPour retrouver le « Free Lunch » Respecter les 4 grandes étapes Notamment les « analyses des dépendances » et « analyses des performances » Avancer de manière itérative Difficile de trouver « la solution » du premier coup Si possible privilégier les capacités de monter en charge ainsi que la simplicité Mesurer régulièrement les performances de vos choix Visual Studio 2010 est votre ami Si vos choix ne vous semblent pas satisfaisants Oser changer votre algorithme pour augmenter ses chances de parallélisation Penser Parallèle C’est en pratiquant régulièrement la méthode présentée que vous gagnerez en réflexes sur l’usage des Patterns parallèles les mieux adaptés à vos besoins
51. Vous n’êtes pas seul !Livres et blogues Mes ouvrages préférés Programmation Parallèle http://msmvps.com/blogs/brunoboucard Portail Microsoft ParallelComputing http://msdn.microsoft.com/en-us/concurrency Patterns for Parallel Programming de Stephen Toub http://www.microsoft.com/downloads/details.aspx?FamilyID=86b3d32b-ad26-4bb8-a3ae-c1637026c3ee&displaylang=en