Comment faire du vrai parallèlisme

Partagez vos scripts, et vos applications AutoIt.
Règles du forum
.
Répondre
JPCare
Niveau 1
Niveau 1
Messages : 3
Enregistré le : jeu. 06 avr. 2023 14:27
Status : Hors ligne

Comment faire du vrai parallèlisme

#1

Message par JPCare »

Autoit n'a pas été conçu pour le parallélisme.

Mais il est possible de programmer l'exécution de processus parallèles en AutoIt.

Pour ce faire, le logiciel en AutoIt doit être spécifiquement programmé en deux parties :
- Principal : initialisation, lancement des processus parallèles, attente des fins d'exécution, consolidation des résultats
- Proc : processus à exécuter en instances indépendantes lancées en parallèle

Il s'agit bien ici de programmer en AutoIt des lancements de processus qui vont s'exécuter en parallèle indépendamment les uns des autres en tant qu'acteurs d'un même projet, et d'en récupérer les résultats pour consolidation.

Comment c'est possible et avec quelle conception adaptée

1/ L'instruction Run d'AutoIt peut lancer un processus sur un cpu thread donné, directement via la commmande start de Windows avec un paramètre /Affinity ou via un utilitaire pour la même fonction.

Evidemment, en vue d'une exécution en plusieurs instances parallèles indépendantes, le processus ainsi lancé doit être dans sa forme compilée en exe files.

Exemples
Run(@ComSpec & " /C start /affinity "&$Affinitymask&" proc.exe")
En répétant l'instruction avec differents "affinity masks" dans $Mask correspondant chacun à un cpuid, on lance autant de proc.exe en instances parallèles.

Autre méthode en utilisant un utilitaire de lancement qui accepte directement un cpuid en paramètre :
$slaunch="StartAffinity.exe proc.exe "&$cpuid
Run($slaunch)

2/ Chaque instance de processus lancé en parallèle doit évidemment être munie de paramètres spécifiques d'exécution, a minima son cpuid, soit via des paramètres de lancement dans l'instruction Run (récupérés en $CmdLine à l'intérieur de chaque instance) ou via quelques instructions envset avant l'instruction Run, dont les paramètres sont récupérés à l'intérieur de chaque instance par des déclarations envget de globals.

3/ En fin d'exécution, chaque instance de processus lancé en parallèle écrit ses résultats dans un fichier spécifique (par exemple sous un nom de fichier comportant le cpuid d'exécution).

4/ Après avoir lancé les processus parallèles, le logiciel principal attend la création des fichiers résultats pour consolidation.


Preuve expérimentale

Deux scripts AutoIt sont joints : Divisoptkim.au3 (Principal) and loopkim.au3 (Proc).

Leur but : trouver les diviseurs entiers d'un nombre entier.

Le script loopkim.au3 doit être compilé par le compilateur AutoIt sur votre machine.

Dans un même répertoire, installez Divisoptkim.au3 et loopkim.exe (plus l'utilitaire StartAffinity.exe seulement si vous utilisez Windows XP - voir in fine le lien pour le télécharger).

Lancez Divisoptkim.au3
(la compilation du script principal n'est pas nécessaire si l'extension au3 est associée à AutoIt sur votre machine).

Les processus loopkim vont s'exécuter en plusieurs instances indépendantes dès que vous aurez saisi un entier suffisamment grand pour justifier le parallélisme.
Quelques suggestions : 5040, 66049, 13 444 333 222 110, 133 444 333 222 110, 333 333 333 333 333.

N'hésitez pas devant les grands nombres, ils occuperont environ 10-15 seconds sur un dualcore, autrement le temps d'exécution sera pratiquement invisible.

Or, ce qui est intéressant, c'est justement de voir la charge de chaque cpu sur le Windows Task Manager (onglet Performances et Resources Monitor pour les versions Windows récentes).

Noter que le logiciel adapte le niveau de parallélisme en fonction de N. Concrètement, si N est relativement petit vis à vis du nombre de cpus disponibles, il réduit le nombre d'instances parallèles pour que chacune soit chargée raisonnablement (c'est-à-dire pour qu'elle s'exécute sur un segment minimum de 100 nombres candidats).

A la fin des processus parallèles, autant de fichiers Journal_x.txt sont créés que d'instances parallèles de loopkim.exe, (avec x = cpuid à partir de 0).

Une exécution du principal avec des paramètres standard (ceux qui sont définis en appuyant sur Return) allouera tous les cpus de la machine avec potentiellement une charge de 100% sur les cpus alloués. Vous pouvez évidemment déclarer un nombre de cpus plus faible que le nombre disponible sur votre machine, cela pourra vous faciliter l'observation de la charge générée via le Task Manager sur chaque cpu.

Si vous choisissez la deuxième méthode d'allocation, seulement les cpus pairs pourront être alloués, et la charge maximale ne pourra donc dépasser 50 %.

Avertissement. Ce logiciel a été testé sur plusieurs versions de Windows, de XP Home 32bit à Windows 11 64bit et sur diverses machines, du bicoeur simple au processeur à 20 threads. D'autres environments peuvent nécessiter des modifications du logiciel.

Pour XP spécialement.
Un utilitaire de lancement est indispensable car on ne peut pas utiliser la commande start, démunie sous XP du paramètre affinity.
Il existe au moins deux utilitaires disponibles.
StartAffinity http://www.adsciengineering.com/StartAffinity/.
Un autre utilitaire se trouve dans les "Heise software archiv" : chercher "launch".
Ces deux utilitaires fonctionnent par ailleurs très bien aussi sur les versions récentes de Windows.

Note. Divisoptkimv2 contient une instruction de rejet des entiers de longueur supérieure à 15 chiffres. C'est pour préserver la justesse des calculs internes. AutoIt gère automatiquement la conversion interne des représentations des entiers de 32 à 64 bits, mais aussi vers le format en virgule flottante, qui est incompatible avec les calculs tels qu'ils sont programmés dans mon logiciel de démo. Pour les très grands nombres, il faudrait utiliser la bibli BigNum, ce qui obligerait à reprogrammer tous les calculs... 05 mai 2023 : finalement, je renonce, mes procédures de division et modulo écrites à la main sont meilleures que les procédures plus génériques de la lib Bib Num...

La conclusion est qu'en cherchant à étendre un langage au-delà des limites de sa conception d'origine, on ne peut qu'engendrer un monstre. Mon petit logiciel de démo est scandaleux parce qu'il reste dans les limites du langage d'origine et démontre comment quelque chose d'impossible, à savoir le vrai parallélisme, peut être réalisé très simplement, mais au prix d'une discipline particulière. Cependant, si vous souhaitez "faire du parallélisme" facilement : il existe d'autres langages pour cela !
Fichiers joints
loopkim.au3
Proc
(998 Octets) Téléchargé 392 fois
Divisoptkimv2.au3
Principal
(5.06 Kio) Téléchargé 400 fois
Modifié en dernier par JPCare le ven. 05 mai 2023 11:21, modifié 4 fois.
Avatar du membre
Nine
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 103
Enregistré le : ven. 17 avr. 2020 01:23
Status : Hors ligne

Re: Comment faire du vrai parallèlisme

#2

Message par Nine »

J'avoue que je n'ai pas lu tout ce mur de mots. Mais j'ai développé des IPCs (voir signature dans le site anglo). À voir si cela te convient...
JPCare
Niveau 1
Niveau 1
Messages : 3
Enregistré le : jeu. 06 avr. 2023 14:27
Status : Hors ligne

Re: Comment faire du vrai parallèlisme

#3

Message par JPCare »

Merci de ton message, cela me donne l'opportunité d'un autre "mur de mots" pour essayer de répondre correctement et surtout utilement pour la communauté.

Au préalable, je déclare avoir lu et compris les fils des forums AutoIt en langue anglaise sur le multithreading, avoir lu et compris les documentations des logiciels de référence Process Lasso et Bill2's Process Manager, avoir lu et trouvé difficile à comprendre les articles des sites MS sur les masques d'affinité...

Il existe une différence d'objectif entre l'implémentation générique des communications entre processus (IPC), le multithreading... et le parallélisme proprement dit.

Le "vrai parallélisme", c'est basique et brutal : je commande les cpus de ma machine pour qu'ils contribuent en parallèle à la réalisation d'une tâche, indépendamment les uns des autres. Je contrôle directement la charge de chaque cpu, alors qu'au contraire, si j'utilise des techniques de multithreading, je n'ai pas à m'en soucier, je fais comme si je disposais d'une puissance infinie.

Mon petit logiciel de démo répartit des segments de nombres à tester entre les cpus qui effectuent en parallèle la recherche des diviseurs, chacun sur son segment alloué. Il résoud deux difficultés : le lancement d'un même processus sur divers cpus, la récupération des résultats.

L'algorithme de recherche des diviseurs n'est pas vraiment optimisé. Le but de l'exercice, c'est de démontrer que le parallélisme est possible seulement avec des instructions basiques d'AutoIt, MAIS au prix d'une conception adaptée du logiciel tel qu'exposée dans le "mur de mots".

C'est donc volontairement que je ne fais aucun usage des techniques développées autour du multithreading et des IPCs, je n'en conteste pas l'intérêt, je traite un autre sujet.
JPCare
Niveau 1
Niveau 1
Messages : 3
Enregistré le : jeu. 06 avr. 2023 14:27
Status : Hors ligne

Re: Comment faire du vrai parallèlisme

#4

Message par JPCare »

Suite de l'expérimentation du parallélime

1/ Nouvelle version v3 du programme principal avec timer et affichage du temps d'exécution
Logiciel plus commode pour afficher les charges cpus
http://www.mitec.cz/tmx.html

2 / Portage du script AutoIt en langage Go : voir Loop.go en pièce jointe (avec fausse extension .au3 pour son ajout en pj)
utilisant une goroutine interne pour le parallélisme.

3/ Le programme Go est BEAUCOUP plus rapide que le script AutoIt, d'un facteur 300 ou plus, c'est à dire concrètement que le programme en Go met 300 fois moins de temps. Précision en passant : tous les cpus sont chargés, on peut le vérifier en ajoutant une boucle à la fin de TheLoop, par exemple une incrémentation d'un des entiers uint64 de 0 jusqu'à 10 000 000 000 par pas de 1.... car sinon l'exécution est tellement rapide que rien n'apparaît sur les graphiques des charges.

Fin de l'expérimentation. Conclusions évidentes...

Pour ma part, j'utiliserai toujours AutoIt en prototypage et pour tous les scripts pour lesquels AutoIt a été développé à l'origine.

17 juin. Le Loop.go est remplacé par une version mieux adaptée au fonctionnement indépendant après compilation. La version originale était ok sous Geany mais sans aucun égard pour la console Windows...
21 juin. Quelques améliorations cosmétiques du Loop.go.

20 août. Après nettoyages du code : mise en ligne des versions "finales"
Fichiers joints
Looping.go.au3
supprimer l'extension fictive .au3
(5.48 Kio) Téléchargé 343 fois
loopkim.au3
(889 Octets) Téléchargé 353 fois
Divisoptkim.au3
(5.33 Kio) Téléchargé 350 fois
Répondre