Personal tools
You are here: Home Calcul Technique Documentation IBM cluster p575 (Power5) Parallel Virtual Machine
Document Actions

Parallel Virtual Machine

Description de la bibliothèque d'échanges de messages PVM

Introduction

Gestion de l'environnement

Communications

  • Buffers
  • Empaquetage des données
  • Envoi et réception des données
  • Dépaquetage des données
  • Gestion des groupes de processus



    Introduction

    PVM (Parallel Virtual Machine) a pour but de faciliter l'écriture d'applications parallèles sur un réseau de stations de travail hétérogènes (modèle MPMD : Multiple Program Multiple Data). L'utilisateur définit un ensemble de machines qui sera vu comme une seule grande machine multiprocesseur à mémoire distribuée. Le terme machine parallèle fait référence à cette machine multiprocesseurs alors que le terme hôte se réfère à l'une des machines membres de l'ensemble. Cette approche permet le regroupement d'hôtes ayant des caractéristiques différentes (machine vectorielle, station graphique, station de travail, cluster, robot de stockage, etc ...). Les communications entre les hôtes se font avec PVM qui prend en charge les conversions de formats nécessaires entre deux machines n'ayant pas les mêmes représentations internes des données. PVM est également conçue pour pouvoir fonctionner avec différents types de réseaux.
    Le site netlib est un site où l'on peut récupérer la distribution PVM ainsi qu'un manuel on-line (décrivant les fonctions PVM) ou sa version  postscript , de même ce lien est la home page de PVM développée par Oak Ridge National Laboratory (ORNL).


    flechehaut

    Gestion de l'environnement

    PVM réalise toutes ses fonctions grâce à des démons qu'il installe, lorsqu'il démarre sur chaque hôte. Ces démons gèreront tout ce qui est communication entre les hôtes. Avant toute exécution d'un programme PVM il faut donc définir l'ensemble des machines hôtes et démarrer PVM. Une fois cette opération effectuée, on peut lancer un programme PVM. Sur le cluster IBM, il suffit de placer un fichier .rhosts dans son $HOME_DIR contenant la ligne suivante :
    localhost  login
    L'environnement est géré à l'aide d'options au travers de la console PVM, pvm, sur la machine hôte. En voici quelques-unes :
    pvm help : les différentes options
    pvm quit : lancement du démon PVM et sortie de la console
    pvm halt : arrêt du démon PVM
    Un utilisateur n'a qu'un seul démon PVM, même si plusieurs applications parallèles s'exécutent en simultané, par conséquent il faut faire attention avant d'arrêter le démon. Il est possible d'insérer ces commandes dans un fichier de soumission, par exemple pour lancer le démon PVM la syntaxe  est :
    echo quit | pvm
    Le sous-programme PVMFMYTID permet d'intégrer le processus appelant dans l'environnement PVM,
    PVMFMYTID (mytid)

    INTEGER   mytid  (OUT)   identificateur (au sens UNIX) du processus.


    La sortie est réalisée par PVMFEXIT :

    PVMFEXIT (irc)

    INTEGER   irc    (OUT)   code de retour.

    Un processus PVM quelconque peut engendrer ("spawner")  d'autres processus (appelés processus "fils") sur la machine parallèle en appelant le sous-programme PVMFSPAWN :

    PVMFSPAWN (task, flag, where, ntask, irc)

    CHARACTER(*) task    (IN)     nom de l'exécutable et chemin absolu,
    INTEGER      flag    (IN)     spécification de la machine cible,
    CHARACTER(*) where   (IN)     nom de la machine cible,
    INTEGER      ntask   (IN)     nombre de processus activés et dimension du tableau suivant,
    INTEGER      tids(*) (OUT)    identificateurs des processus activés,
    INTEGER      irc     (OUT)    code de retour.

    Les valeurs des arguments flag et where sont données par le tableau suivant :
     

    flag where
    PVMTASKDEFAULT '*'
    PVMTASKHOST nom de la machine
    PVMTASKARCH nom de l'architecture

    Enfin, les processus "fils" peuvent connaitre l'identificateur du processus "père" qui les a générés à l'aide du sous-programme PVMFPARENT :

    PVMFPARENT (tid)

    INTEGER       tid     (OUT)    identificateur du processus père

    Si le processus appelant ce sous-programme n'a pas de processus père, tid vaut alors PVMNOPARENT.

    Exemple :

    PROGRAM identification

    include 'fpvm3.h'

    INTEGER  mytid, tid
    INTEGER  itids (4)
    INTEGER  irc
     

    C Initialisation
    CALL PVMFMYTID (mytid)
    C Nombre de processus
    CALL PVMFPARENT (tid)
    C Test
    IF ( tid .EQ. PVMNOPARENT ) THEN

       WRITE (6, *) 'Je n'ai pas de processus père'

       CALL PVMFSPAWN ('identification', PVMTASKDEFAULT, '*', 4, itids, irc)

    ELSE

       WRITE (6, *) 'Mon tid est : ', mytid, ', celui de mon processus pere est : ', tid

    ENDIF
     

    C Sortie
    CALL PVMFEXIT (irc)

    STOP
    END


    flechehaut

    Communications

    Une communication point-à-point a lieu entre deux processus, l'un est appelé émetteur, l'autre récepteur, identifiés par leur rang. Il s'agit de la communication de base de MPI et les opérations effectuées sont un send et un receive. Il existe différentes manières d'effectuer la communication. De manière générale, les paramètres nécessaires à sa construction sont :
    • les rangs des processus émetteur et récepteur,
    • l'étiquette du message,
    • le type des données échangées,
    • les données.
    Un code de retour fait partie des arguments, sa valeur (si négative) indique le type de problème rencontré.
    L'envoi d'un message se fait en trois étapes. En premier, une mémoire tampon (buffer), doit être initialisée par un appel à la routine PVMFINITSEND. Ensuite, le message doit être enpaqueté dans ce buffer en utilisant PVMFPACK. Enfin, le message ainsi préparé peut être envoyé à un autre processus en appelant PVMFSEND ou en diffusion collective par PVMFMCAST. Un message est reçu en appelant une routine de réception soit bloquante, soit non bloquante, puis en dépaquetant les objets du buffer de réception. On peut paramétrer les arguments des routines de réception de telle sorte qu'elles acceptent tous les messages ou les messages d'une source précise, ou ceux munis d'une étiquette (tag) particulière ou encore un message d'une source donnée avec une étiquette précise.
     
    • Buffers
    Si le développeur utilise un unique buffer d'envoi (ce qui est le cas général), la seule routine nécessaire est PVMFINITSEND :
    PVMFINITSEND (encoding, bufid)

    INTEGER    encoding     (IN)        type du codage des données,
    INTEGER    bufid        (OUT)       identificateur du buffer.

    Cet appel est effectué avant tout nouvel empaquetage de données dans le buffer : il efface le buffer d'envoi et en crée un nouveau pour le nouveau message. Le type de codage des données est spécifié par l'argument encoding et en sortie bufid contient l'identificateur du buffer. Les options de codage sont les suivantes :

    • PvmDataDefault : codage XDR utilisé par défaut si PVM n'a pas d'information sur l'hétérogénéité de la machine parallèle virtuelle,
    • PvmDataRaw : pas de codage des données, les messages sont laissés dans leur forme initiale,
    • PvmDataInPlace : les données sont laissées à leur place, le buffer ne contient que les tailles et les adresses des objets à envoyer. Cela permet de ne pas dupliquer les données mais cela suppose aussi que le processus émetteur ne les modifiera pas.
    Si le développeur sait que le destinataire "comprend" le codage des données initiales alors il peut utiliser l'option PvmDataRaw pour éviter un codage inutile. Dans le cas où le processus cible ne sait pas lire le format alors il génère une erreur durant le dépaquetage.

    Pour manipuler plusieurs buffers dans une même application, il faut utiliser les routines suivantes. Dans PVM, il n'y a qu'un seul buffer actif d'envoi et un seul buffer actif de réception à la fois. Par contre, il peut y avoir plusieurs buffers et ainsi empaqueter et envoyer des données avec eux. Les opérations d'empaquetage, envoi, réception et dépaquetage ne concernent que le buffer actif.

    PVMFMKBUF (encoding, bufid)

    INTEGER    encoding     (IN)        type du codage des données,
    INTEGER    bufid        (OUT)       identificateur du buffer.

    La routine PVMFMKBUF crée un nouveau buffer d'envoi et précise la méthode de codage pour l'empaquetage des données. En retour, l'argument bufid contient l'identificateur. La routine PVMFFREEBUF libère le buffer d'identificateur bufid.

    PVMFFREEBUF (bufid, irc)

    INTEGER    bufid        (IN)        identificateur du buffer,
    INTEGER    irc          (OUT)       code de retour.

    Cela doit être fait lorsque le message a été envoyé et que le buffer est devenu inutile. Ces appels ne sont pas nécessaires en cas d'utilisation de PVMFINITSEND.
    Pour connaitre les identificateurs des buffers actifs d'envoi et de réception on utilise respectivement les routines suivantes :

    PVMFGETSBUF (bufid)

    INTEGER    bufid        (OUT)       identificateur du buffer d'envoi.
     

    PVMFGETRBUF (bufid)

    INTEGER    bufid        (IN)        identificateur du buffer de réception.

    On peut spécifier le buffer actif d'envoi avec PVMFSETSBUF et de réception avec PVMFSETRBUF. Elles rendent actif le buffer d'identificateur bufid, sauvegardent l'état du buffer précédent et renvoient l'identificateur du buffer précédemment actif dans oldbuf :
     

    PVMFSETSBUF (bufid, oldbuf)

    INTEGER    bufid        (IN)       identificateur du buffer d'envoi activé,
    INTEGER    oldbuf       (OUT)      identificateur du buffer désactivé.
     

    PVMFSETRBUF (bufid, oldbuf)

    INTEGER    bufid        (IN)       identificateur du buffer de réception activé,
    INTEGER    oldbuf       (OUT)      identificateur du buffer désactivé.

    Si l'argument bufid est transmis à zéro dans PVMFSETSBUF ou PVMFSETRBUF alors le buffer courant est sauvegardé et il n'y a pas de buffer actif.
     
    • Empaquetage des données
    L'empaquetage de données en C se fait à l'aide de routines spécifiques à chaque type de données impliqué :
     
    Routine Type C de la donnée
    PVM_PKBYTE char
    PVM_PKCPLX float
    PVM_PKDCPLX double
    PVM_PKDOUBLE double
    PVM_PKFLOAT float
    PVM_PKINT int
    PVM_PKLONG long
    PVM_PKSHORT short
    PVM_PKSTR char
    PVM_PACKF  ////

    Chacune d'entre-elles empaquète un tableau du type de données dans le buffer d'envoi actif. Elles peuvent être appelées à plusieurs reprises pour un même message, ainsi un message peut contenir plusieurs tableaux de types de données différents. Les structures C doivent être envoyées en empaquetant chacun de leurs champs. Le dépaquetage doit se faire dans le même ordre que l'empaquetage. Les arguments de chaque routine sont dans l'ordre : un pointeur sur le premier élément à envoyer, le nombre total d'éléments du tableau, et le pas de parcours. Seule exception, la fonction PVM_PKSTR qui n'a besoin que d'un pointeur sur CHAR.

    int info = pvm_pkbyte( char *cp, int nitem, int stride )
    int info = pvm_pkcplx( float *xp, int nitem, int stride )
    int info = pvm_pkdcplx ( double *zp, int nitem, int stride )
    int info = pvm_pkdouble ( double *dp, int nitem, int stride )
    int info = pvm_pkfloat ( float *fp, int nitem, int stride )
    int info = pvm_pkint ( int *np, int nitem, int stride )
    int info = pvm_pklong ( long *np, int nitem, int stride )
    int info = pvm_pkshort ( short *np, int nitem, int stride )
    int info = pvm_pkstr ( char *cp )
    int info = pvm_packf ( const char *fmt, ... )

    Une donnée de type complex est supposée être deux variables float consécutives, il en est de même pour le type double complexe avec deux variables double. Toutes les variables sont supposées être des pointeurs si les arguments nitem et stride sont présents, autrement il s'agit de scalaires. La fonction PVM_PACKF utilise un formatage similaire à la fonction C printf pour spécifier les données et la manière de les placer dans le buffer d'envoi (voir la manpage de PVM_PACKF). Une seule routine Fortran gère l'empaquetage des données : PVMFPACK :

    PVMFPACK (what, xp, nitem, stride, irc)

    INTEGER    what      (IN)      type de données à empaqueter,
    <type>     xp(*)     (IN)      donnée (adresse initiale) à envoyer,
    INTEGER    nitem     (IN)      nombre d'éléments à envoyer,
    INTEGER    stride    (IN)      pas,
    INTEGER    irc       (OUT)     code de retour.

    Le nombre de caractères dans une chaine de caractères doit être transmis à cette subroutine à l'aide de l'argument nitem. L'entier what précise le type de données envoyées, ses valeurs sont :
     

    Type Valeur
    STRING 0
    BYTE1 1
    INTEGER2 2
    INTEGER4 3
    REAL4 4
    COMPLEX8 5
    REAL8 6
    COMPLEX16 7

     
    • Envoi et réception des données
    La subroutine PVMFSEND donne une étiquette tag au message présent dans le buffer d'envoi actif et l'envoie immédiatement au processus destinataire tid :
    PVMFSEND ( tid, tag, irc)

    INTEGER    tid     (IN)      identificateur du processus destinataire,
    INTEGER    tag     (IN)      étiquette du message,
    INTEGER    irc     (OUT)     code de retour.

    La routine PVMFMCAST donne une étiquette tag au message présent dans le buffer d'envoi actif et le diffuse à tous les tâches spécifiées dans le tableau tids (le processus émetteur exclu). Ce tableau a pour dimension ntask.

    PVMFMCAST ( ntask, tids, tag, irc)

    INTEGER    task    (IN)      nombre de tâches destinataires et dimension du tableau suivant,
    INTEGER    tids(*) (IN)      tableau des identificateurs des processus destinataires,
    INTEGER    tag     (IN)      étiquette du message,
    INTEGER    irc     (OUT)     code de retour.

    La routine PVMFPSEND permet d'empaqueter et d'envoyer un tableau de données de type simple à une tâche identifiée.

    PVMFPSEND ( tid, tag, buffer, length, type, irc )

    INTEGER    tid       (IN)      identificateur du processus destinataire,
    INTEGER    tag       (IN)      étiquette du message,
    INTEGER    buffer(*) (IN)      donnée (adresse initiale) à envoyer,
    INTEGER    length    (IN)      taille du buffer (en multiple de la taille d'un élément),
    INTEGER    type      (IN)      type de données à envoyer,
    INTEGER    irc       (OUT)     code de retour.


    En Fortran, le type des données est le même que pour PVMFPACK (voir tableau ci-dessus). En C l'argument type est lun des suivants :
     

    PVM_STR PVM_FLOAT
    PVM_BYTE PVM_CPLX
    PVM_SHORT PVM_DOUBLE
    PVM_INT PVM_DCPLX
    PVM_LONG PVM_UINT
    PVM_USHORT PVM_ULONG

    Il y a différentes manières de réceptionner un message, de plus il n'y a pas obligatoirement une correspondance entre un send et un recv, i.e. entre un PVMFPSEND et un PVMFPRECV. N'importe laquelle des routines suivantes peut être utilisée pour réceptionner un message, qu'il soit envoyé en point-à-point ou collectivement.

    PVMFRECV (tid, tag, bufid)

    INTEGER   tid   (IN)    Identificateur du processus expéditeur,
    INTEGER   tag   (IN)    Etiquette du message,
    INTEGER   bufid (OUT)   Identificateur du nouveau buffer actif.

    Si l'argument tid vaut -1 alors tout processus est accepté comme expéditeur. Si tag vaut -1 alors tout message est accepté. Si bufid est négatif alors sa valeur correspond à un code d'erreur. La routine de réception bloquante PVMFRECV attend jusqu'à ce qu'un message portant l'étiquette tag arrive du processus tid (ou que leur valeur soit -1). Elle place le message dans un nouveau buffer de réception ainsi activé. Le précédent buffer activé est alors libéré à moins qu'il n'ait été sauvegardé par un appel à PVMSETRBUF.

    PVMFNRECV (tid, tag, bufid)

    INTEGER   tid   (IN)    Identificateur u processus expéditeur,
    INTEGER   tag   (IN)    Etiquette du message,
    INTEGER   bufid (OUT)   Identificateur du nouveau buffer actif.

    Si le message spécifié par tag n'est pas encore arrivé, alors la réception non bloquante PVMFNRECV rend la main avec l'argument bufid mis à zéro. Cette routine peut être appelée de nombreuses fois pour le même message et voir s'il est arrivé. S'il n'y a plus de travail à effectuer en attendant on peut alors mettre un PVMFRECV. Si un message d'étiquette tag arrive du processus tid (ou que leur valeur soit -1), elle le place dans un nouveau buffer de réception (ainsi crée) et renvoie l'identificateur du buffer. Le précédent buffer activé est alors libéré à moins qu'il n'ait été sauvegardé par un appel à PVMSETRBUF.

    PVMFPROBE (tid, tag, bufid)

    INTEGER   tid   (IN)    Identificateur du processus expéditeur,
    INTEGER   tag   (IN)    Etiquette du message,
    INTEGER   bufid (OUT)   Identificateur du nouveau buffer actif.

    Si le message spécifié par tag n'est pas encore arrivé alors PVMFPROBE renvoie l'argument bufid mis à zéro. Autrement, elle renvoie l'identificateur du buffer, mais n'effectue pas la réception. Cette routine peut être appelée de nombreuses fois pour le même message et voir s'il est arrivé. En complément, un appel à PVMFBUFINFO avec l'identificateur du buffer permet d'obtenir des informations à propos du message avant de le réceptionner.

    PVMFBUFINFO (bufid, bytes, tag, tid, irc)

    INTEGER   bufid (IN)    Identificateur du buffer de réception,
    INTEGER   bytes (OUT)   Longueur totale du message en octets,
    INTEGER   tag   (OUT)   Etiquette du message,
    INTEGER   tid   (IN)    Identificateur du processus source,
    INTEGER   irc   (OUT)   Code de retour.

    Elle peut être employée pour déterminer l'étiquette et/ou la source précises d'un message pour lequel ces paramètres valent -1 (i.e. n'importe quelle étiquette et/ou n'importe quelle source).
    PVM fournit une version "timeout" de réception, i.e. dans le cas ou un message en attente de réception ne sera jamais envoyé, une réception bloquante posera problème. Le développeur peut choisir d'abandonner au bout d'un temps d'attente donné. La routine  PVMFTRECV permet ainsi au programmeur de spécifier un temps limite d'attente.

    PVMFTRECV (tid, tag, sec, usec, bufid)

    INTEGER   tid   (IN)    Identificateur du processus source,
    INTEGER   tag   (IN)    Etiquette du message,
    INTEGER   sec   (IN)    Définit le temps d'attente,
    INTEGER   usec  (IN)    Définit le temps d'attente,
    INTEGER   bufid (IN)    Identificateur du buffer de réception.

    La routine PVMFTRECV bloque jusqu'à ce qu'un message portant l'étiquette tag arrive du processus tid (ou que leur valeur soit -1). Elle place le message dans un nouveau buffer de réception ainsi activé (le précédent buffer activé est alors libéré à moins qu'il n'ait été sauvegardé par un appel à PVMSETRBUF). Si aucun message spécifié n'arrive durant le temps d'attente prédéfini alors PVMFTRECV rend la main (sans générer de message). Si la durée fournie est très grande alors PVMFTRECV se comporte comme PVMFRECV. Si la période est mise à zéro alors elle se comporte comme PVMFNRECV. Ainsi PVMFTRECV sert d'intermédiaire entre PVMFRECV et PVMFNRECV, i.e. entre les réception bloquante et non bloquante.

    La routine PVMFPRECV combine les fonctionnalités d'une réception bloquante et du dépaquetage du buffer. La réception a lieu directement dans un buffer sans qu'il n'y ait de dépaquetage. C'est en quelque sorte l'équivalent en réception de PVMFPSEND :

    PVMFPRECV ( tid, tag, buffer, length, type, atid, atag, alen, irc )

    INTEGER    tid       (IN)      identificateur du processus destinataire,
    INTEGER    tag       (IN)      étiquette du message,
    INTEGER    buffer(*) (IN)      donnée (adresse initiale) de réception,
    INTEGER    length    (IN)      taille du buffer (en multiple de la taille d'un élément),
    INTEGER    type      (IN)      type de données à recevoir,
    INTEGER    atid      (OUT)     véritable identificateur de l'expéditeur,
    INTEGER    atag      (OUT)     véritable étiquette du message,
    INTEGER    alen      (OUT)     véritable longueur du message,
    INTEGER    irc       (OUT)     code de retour.

    • Dépaquetage des données
    Le dépaquetage de données en C se fait à l'aide de routines spécifiques à chaque type de données impliqué :
     
    Routine Type C de la donnée
    PVM_UPKBYTE char
    PVM_UPKCPLX float
    PVM_UPKDCPLX double
    PVM_UPKDOUBLE double
    PVM_UPKFLOAT float
    PVM_UPKINT int
    PVM_UPKLONG long
    PVM_UPKSHORT short
    PVM_UPKSTR char
    PVM_UNPACKF  ////

    Chacune d'entre-elles dépaquète un tableau du type de données dans le buffer de réception actif. Elles doivent correspondre à leur analogue d'empaquetage pour les arguments de type, de nombre d'éléments et de pas; le dépaquetage doit se faire dans le même ordre que l'empaquetage. Les arguments de chaque routine sont dans l'ordre : un pointeur sur le premier élément à envoyer, le nombre total d'éléments du tableau, et le pas de parcours. Seule exception, la fonction PVM_UPKSTR qui n'a besoin que d'un pointeur sur char.

    int info = pvm_upkbyte( char *cp, int nitem, int stride )
    int info = pvm_upkcplx( float *xp, int nitem, int stride )
    int info = pvm_upkdcplx ( double *zp, int nitem, int stride )
    int info = pvm_upkdouble ( double *dp, int nitem, int stride )
    int info = pvm_upkfloat ( float *fp, int nitem, int stride )
    int info = pvm_upkint ( int *np, int nitem, int stride )
    int info = pvm_upklong ( long *np, int nitem, int stride )
    int info = pvm_upkshort ( short *np, int nitem, int stride )
    int info = pvm_upkstr ( char *cp )
    int info = pvm_unpackf ( const char *fmt, ... )

    Une donnée de type complex est supposée être deux variables float consécutives, il en est de même pour le type double complexe avec deux variables double. Toutes les variables sont supposées être des pointeurs si les arguments nitem et stride sont présents, autrement il s'agit de scalaires. La fonction PVM_UNPACKF utilise un formatage similaire à la fonction C printf pour spécifier les données et la manière de les placer dans le buffer d'envoi (voir la manpage de PVM_UNPACKF). Une seule routine Fortran gère le dépaquetage des données : PVMFUNPACK.

    PVMFUNPACK (what, xp, nitem, stride, irc)

    INTEGER    what      (IN)      type de données à dépaqueter,
    <type>     xp(*)     (IN)      donnée (adresse initiale) à dépaqueter,
    INTEGER    nitem     (IN)      nombre d'éléments à recevoir,
    INTEGER    stride    (IN)      pas,
    INTEGER    irc       (OUT)     code de retour.

    Le nombre de caractères dans une chaine de caractères doit être transmis à cette subroutine à l'aide de l'argument nitem. L'entier what précise le type de données envoyées, ses valeurs sont :
     

    Type Valeur
    STRING 0
    BYTE1 1
    INTEGER2 2
    INTEGER4 3
    REAL4 4
    COMPLEX8 5
    REAL8 6
    COMPLEX16 7


    flechehaut

    Gestion des groupes de processus

    On regroupe des processus PVM à l'aide de la routine PVMFJOINGROUP qui permet d'inclure le processus appelant dans un groupe. En sortie, ce processus reçoit son rang (numéro d'instance) dans le groupe, une valeur (unique au sein du groupe) comprise entre 0 et le nombre de processus du groupe - 1, qui permet de l'identifier. Le premier processus qui effectue l'appel crée le groupe.
    PVMFJOINGROUP (group, irank)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      irank   (OUT)    rang du processus.

    De même, on peut quitter un groupe à l'aide de la routine PVMFLVGROUP:

    PVMFLVGROUP (group, irc)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      irc     (OUT)    code de retour.

    N'importe quelle tâche PVM peut rejoindre ou quitter un groupe de processus, n'importe quand et sans devoir en informer une autre tâche. En cas de sortie et de réentrée, le numéro d'instance (le rang) n'est pas forcément le même : la tâche entrante reçoit le plus petit numéro disponible. En cas de sortie de tâches du groupe, c'est au développeur de maintenir un ensemble contigu des numéros d'instance si l'algorithme le nécessite. De plus, un processus peut appartenir à plusieurs groupes; enfin elle peut diffuser des messages vers un groupe dont elle ne fait pas partie.

    La routine PVMFGETTID renvoie l'identificateur d'un processus dont on connait le numéro d'instance dans un groupe donné :

    PVMFGETTID (group, irang, tid)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      irank   (IN)     numéro d'instance du processus dans le groupe,
    INTEGER      tid     (OUT)    identificateur du processus.

    Deux processus qui n'ont pas de connaissance réciproque peuvent obtenir l'identificateur de l'autre processus en intégrant un groupe commun. La routine PVMFGETINST renvoie le numéro d'instance d'un processus dont on connait l'identificateur et un groupe d'appartenance :

    PVMFGETINST (group, tid, irang)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      tid     (IN)     identificateur du processus,
    INTEGER      irank   (OUT)    numéro d'instance du processus dans le groupe.

    La routine PVMFGSIZE retourne le nombre de processus d'un groupe donné :

    PVMFGSIZE (group, size)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      size    (OUT)    nombre de processus dans le groupe.

    En appelant PVMFBARRIER le processus bloque jusqu'à ce qu'un total de count membres d'un groupe ont fait de même.

    PVMFBARRIER (group, count, irc)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      count   (IN)     identificateur du processus,
    INTEGER      irc     (OUT)    code de retour.

    En général count devrait être égal au nombre de membres d'un groupe. Fournir un nombre de processus est nécessaire du fait de la gestion dynamique des processus au sein des groupes PVM. En effet, PVM ne peut pas connaitre à un instant donné le nombre de processus. Les situations suivantes engendrent des erreurs : appeler PVMFBARRIER avec un groupe par un processus qui n'en fait pas partie, différents processus effectuent l'appel mais avec des valeurs différentes de count.

    La routine PVMFBCAST assigne une étiquette tag et effectue une diffusion générale à toutes les tâches membres du groupe spécifié en argument (à l'exception du processus émetteur) au moment où l'appel est effectué. Si des processus intègrent le groupe durant le broadcast, il est possible qu'ils ne reçoivent pas le message; par contre en cas de sortie, ils reçoivent le message.

    PVMFBCAST (group, tag, irc)

    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      tag     (IN)     étiquette du message,
    INTEGER      irc     (OUT)    code de retour.

    La routine PVMFREDUCE effectue une opération d'arithmétique globale au sein d'un groupe, par exemple une somme globale ou la recherche du maximum. Le résultat est reçu par le processus appelé root.

    PVMFREDUCE (func, data, count, type, tag, group, root, irc)

    EXTERNAL     func    (IN)     fonction à appliquer,
    <type>       data    (IN/OUT) donnée (adresse initiale) à réduire,
    INTEGER      count   (IN)     nombre d'éléments dans le tableau,
    INTEGER      type    (IN)     type de données des éléments du tableau,
    INTEGER      tag     (IN)     étiquette du message,
    CHARACTER(*) group   (IN)     nom du groupe de processus,
    INTEGER      root    (IN)     rang du processus destinataire de l'opération,
    INTEGER      irc     (OUT)    code de retour.

    func est le nom d'une fonction appliquée aux données transmises dans data. Ses valeurs prédéfinies sont :
     

    PvmMax PvmMin PvmSum PvmProduct

    Il est possible de construire ses propres fonctions.
    Ces fonctions sont implantées pour les types de données suivants :
     

    Type PVM de la donnée Type C de la donnée Type PVM de la donnée Type Fortran de la donnée
    PVM_BYTE byte BYTE1 CHARACTER
    PVM_SHORT short INTEGER2 INTEGER*2
    PVM_INT int INTEGER4 INTEGER*4
    PVM_FLOAT float INTEGER8 INTEGER*8
    PVM_CPLX complex REAL4 REAL*4
    PVM_DOUBLE double REAL8 REAL*8
    PVM_LONG long int  COMPLEX8 COMPLEX*8
    PVM_USHORT unsigned short int COMPLEX16 COMPLEX*16
    PVM_UINT unsigned int
    PVM_ULONG unsigned long

    L'opération de réduction est effectuée élément par élément au sein du tableau data. Par exemple, si le tableau contient deux nombre réels et la fonction de réduction est PvmMax  alors le tableau résultat data du processus root contiendra deux valeurs : la première correspond au produit de tous les premiers réels et la seconde au produit de tous les seconds réels.

    La routine PVMFSCATTER distribue un tableau à chaque membre d'un groupe de processus. Le processus émetteur, est identifié par son rang dans le groupe.Tous les membres du groupe doivent appeler cette subroutine pour que chacun reçoive une portion du tableau data. Le i-ème membre du groupe reçoit num éléments de type type du tableau data à partir de l'indice i*num , qui sont stockés dans son tableau result.

    PVMFSCATTER ( result, data, num, type, tag, group, root, irc )

    <type>       result(*) (OUT)    donnée (adresse initiale) de réception,
    <type>       data(*)   (IN)     donnée (adresse initiale) à distribuer,
    INTEGER      num       (IN)     nombre d'éléments à envoyer à chaque membre du groupe,
    INTEGER      type      (IN)     type de données des éléments du tableau,
    INTEGER      tag       (IN)     étiquette du message,
    CHARACTER(*) group     (IN)     nom du groupe de processus,
    INTEGER      root      (IN)     rang du processus auteur de l'opération,
    INTEGER      irc       (OUT)    code de retour.

    La listes des type de données figure dans le tableau ci-dessus.
    Dans un appel à PVMFGATHER, chaque processus du groupe (root inclus) envoie ses données au processus root qui les reçoit et les stocke dans l'ordre des rangs des processus. Tous les membres du groupe doivent appeler cette subroutine pour pouvoir envoyer une portion du tableau data. Le i-ème membre du groupe envoie num éléments de type type du tableau data, qui sont stockés dans le tableau result du processus root à partir de l'indice i*num.

    PVMFGATHER ( result, data, num, type, tag, group, root, irc )

    <type>       result(*) (OUT)    donnée (adresse initiale) de réception,
    <type>       data(*)   (IN)     donnée (adresse initiale) à fusionner,
    INTEGER      num       (IN)     nombre d'éléments envoyés par chaque membre du groupe,
    INTEGER      type      (IN)     type de données des éléments du tableau,
    INTEGER      tag       (IN)     étiquette du message,
    CHARACTER(*) group     (IN)     nom du groupe de processus,
    INTEGER      root      (IN)     rang du processus auteur de l'opération,
    INTEGER      irc       (OUT)    code de retour.

    La liste des type de données figure dans le tableau ci-dessus.

    Ces deux subroutines ne sont pas bloquantes. Si une tâche appelle une de ces fonctions et sort du groupe avant que le processus root n'ait effectué lui-même l'appel alors une erreur peut survenir.

    Exemples de programme PVM Maître/Esclave


    flechehaut

    Powered by Plone CMS, the Open Source Content Management System

    This site conforms to the following standards: