« Code parallèle » : différence entre les versions
m (a renommé Parallel coding (langage) en Code parallèle) |
|||
Ligne 153 : | Ligne 153 : | ||
[[Category:Langage]] | [[Category:Langage]] | ||
[[Category: | [[Category:Latest]] | ||
[[Category:Parallèle]] | [[Category:Parallèle]] |
Version du 11 mars 2013 à 10:20
stock}} |
La programmation parallèle permet de distribuer des boucles de traitement sur l'ensemble des coeurs disponibles.
Près-requis
Pour être parallélisable une boucle de traitement doit vérifier les conditions suivantes :
- Chaque exécution du corps de boucle doit être indépendante.
- Il n'existe pas de mécanisme de synchronisation de variable de sorte que les exécutions parallèles ne doivent pas partager d'objet ou de variable.
- La boucle doit utiliser un pattern de code ForEachP ou doit être inclue dans une transaction utilisant un pattern with transaction.
- Les patterns de code implémentent le mécanisme le synchronisation des différents exécuteurs.
- La boucle de traitement doit appeler une méthode qui exécute la tâche.
- Ce sont l'exécution des méthodes qui sont parallélisées.
Pool d'exécuteur
L'exécution d'une méthode en parallèle est pris en charge par des exécuteurs (working thread) qui sont gérés en pool. La taille de ce pool est déterminée par le nombre de coeurs disponibles et la configuration réseau.
La taille de ce pool est déterminée automatiquement, toutefois à des fins de test il est possible de changer celle-ci dans le dialogue de préférence du concepteur de modèle onglet "Code parallèle"
Mot clé "parallel"
Ce mot clé se place devant l'appel d'une méthode pour indiquer au compilateur de générer l'appel parallèle.
<source lang="delphi"> var tk:Int64; begin
tk := GetTickCount; try // use a pattern to sync the workers withP Transaction do for var idx:=1 to 10 do begin parallel doCreateA(idx); end; finally tk := GetTickCount-tk; showmessage(Format('%s ms',[TickToString(tk)])); end;
end; </source>
Paramètres des méthodes parallélisées
Lorsqu'une méthode est exécutée en parallèle ses paramètres sont copiés dans le contexte de l'exécuteur.
Certain paramètres sont gérés avec attention :
- Les objets sont tenus par référence et non pas par copie.
- les liste d'objet sont dupliquées (mais pas les objets qu'elles contiennent)
Exemple :
Dans cet exemple une liste d'objet a traité est passé à la méthode doProcessList, cette liste est ensuite réinitialisée sans que cela impacte l'exécution en cours de l'exécuteur.
<source lang="delphi"> var list:WFClasseAList; inst:WFClasseA; cursor:WFClasseACursor; count:Integer; tk:Int64; begin
List := WFClasseA.CreateList; Cursor := WFClasseA.CreateCursorWhere(,,true,['A',1]); tk := GetTickCount; try withP long(100) transaction begin foreachP inst in cursor index count do begin List.AddRef(inst); if List.Count=100 then begin // start a working thread parallel doProcessList(List); // list.Clear is safe because the list has been cloned List.Clear; end; end; if List.Count<>0 then doProcessList(List); end; finally tk := GetTickCount-tk; showmessage(Format('%d %s ms',[count,TickToString(tk)])); end;
end; </source>
Modèle de transaction
En programmation série deux modèles de transaction sont utilisables :
- Transaction en mémoire
- Les objets de la transaction sont maintenu en mémoire durant le temps de la transaction. Ce modèle est adapté lorsque le nombre d'objet traité est limité.
- Transaction longue
- Les objets de transaction sont envoyés régulièrement au serveur de données ; ce modèle est adapté lorsque le nombre d'objet traité est grand.
En programmation parallèle un nouveau critère intervient :
- Transaction partagée
- Chaque exécuteur partage la même transaction globale.
- Transaction isolée
- Chaque exécuteur utilise sa propre transaction.
Mémoire | Longue | |
---|---|---|
Partagée | Voir le code MP | Voir le code LP |
Isolée | Voir le code MI | Voir le code LI |
Messages émis par le code
Le code exécuté en parallèle peut émettre des messages vers l'interface utilisateur.
![]() |
Tip :
|
Interruption du traitement
Lorsqu'une boucle parallélisée est interrompue, par exemple par une instruction break, l'interruption ne sera effective qu'à la fin des exécutions déjà démarrées. En d'autre terme les exécutions déjà lancées se poursuivent.
<source lang="delphi"> begin
... foreachP I in C index ACount on except continue do begin // check abort if UserAbort then begin doLogFailure(nil,S,_TP('Traitement interrompu')); break; end; .... end; // all working thread terminated even if a break has occured.
end; </source>
Gestion des exceptions
Les exceptions qui se produisent dans un exécuteur sont capturées, la prise en compte dans la boucle principale dépend du mode de gestion de celle-ci.
- Mode break
- L'exception arrête la boucle est re-déclenchée dans la boucle principale (main thread)
- Mode continue
- L'exécution est capturée et ignorée.
Imbrication
L'exécution parallèle peut être imbriquée, c'est à dire qu'une méthode exécutée en parallèle peut elle même exécutée une boucle parallélisée.