LAPI_Amsendv Sous-routine

Objectif

Transfère un vecteur utilisateur vers une tâche distante, obtenant l'adresse cible sur la tâche distante à partir d'un gestionnaire d'en-tête spécifié par l'utilisateur.

Bibliothèque

Bibliothèque de disponibilité (liblapi_r.a)

Syntaxe C

#include <lapi.h>
 
typedef void (compl_hndlr_t) (hndl, user_info);
lapi_handle_t  *hndl;       /* the LAPI handle passed in from LAPI_Amsendv */
void           *user_info;  /* the buffer (user_info) pointer passed in    */
                            /* from vhdr_hndlr (void *(vhdr_hndlr_t))      */
 
typedef lapi_vec_t *(vhdr_hndlr_t) (hndl, uhdr, uhdr_len, len_vec, comp_h, uinfo);
 
lapi_handle_t  *hndl;       /* pointer to the LAPI handle passed in from LAPI_Amsendv */
void           *uhdr;       /* uhdr passed in from LAPI_Amsendv                       */
uint           *uhdr_len;   /* uhdr_len passed in from LAPI_Amsendv                   */
ulong          *len_vec[ ]; /* vector of lengths passed in LAPI_Amsendv               */
compl_hndlr_t **comp_h;     /* function address of completion handler                 */
                            /* (void (compl_hndlr_t)) that needs to be                */
                            /* filled out by this header handler function             */
void          **user_info;  /* pointer to the parameter to be passed                  */
                            /* in to the completion handler                           */
 
int LAPI_Amsendv(hndl, tgt, hdr_hdl, uhdr, uhdr_len, org_vec, 
                 tgt_cntr, org_cntr, cmpl_cntr);
 
lapi_handle_t   hndl;
uint            tgt;
void           *hdr_hdl;
void           *uhdr;
uint            uhdr_len;
lapi_vec_t     *org_vec;
lapi_cntr_t    *tgt_cntr;
lapi_cntr_t    *org_cntr;
lapi_cntr_t    *cmpl_cntr; 

Syntaxe FORTRAN

include 'lapif.h'
 
INTEGER SUBROUTINE COMPL_H (hndl, user_info)
INTEGER hndl
INTEGER user_info(*)

INTEGER FUNCTION VHDR_HDL (hndl, uhdr, uhdr_len, len_vec, comp_h, user_info)
INTEGER hndl
INTEGER uhdr      
INTEGER uhdr_len
INTEGER (KIND=LAPI_LONG_TYPE) :: len_vec
EXTERNAL INTEGER FUNCTION comp_h
TYPE (LAPI_ADDR_T) :: user_info

LAPI_AMSENDV(hndl, tgt, hdr_hdl, uhdr, uhdr_len, org_vec, 
             tgt_cntr, org_cntr, cmpl_cntr, ierror)
INTEGER hndl
INTEGER tgt
EXTERNAL INTEGER FUNCTION hdr_hdl
INTEGER uhdr
INTEGER uhdr_len
TYPE (LAPI_VEC_T) :: org_vec
INTEGER (KIND=LAPI_ADDR_TYPE) :: tgt_cntr
TYPE (LAPI_CNTR_T) :: org_cntr 
TYPE (LAPI_CNTR_T) :: cmpl_cntr 
INTEGER ierror
 

Descriptif

Communication point à point Type of call: (non bloquante)

LAPI_Amsendv est la version vectorielle de l'appel LAPI_Amsend . Vous pouvez l'utiliser pour spécifier des descriptions multidimensionnelles et non contiguës des données à transférer. Alors que les appels LAPI réguliers permettent la spécification d'une seule adresse de mémoire tampon de données et de longueur, les versions vectorielles permettent la spécification d'un vecteur d'adresses et de combinaisons de longueur. Des informations supplémentaires sont autorisées dans la description des données sur la tâche d'origine et la tâche cible.

Utilisez cette sous-routine pour transférer un vecteur de données vers une tâche cible, lorsque vous souhaitez qu'un gestionnaire s'exécute sur la tâche cible avant le début de la distribution des messages ou la fin de la distribution des messages.

Pour utiliser LAPI_Amsendv, vous devez fournir un gestionnaire d'en-tête qui renvoie l'adresse de la description du vecteur cible que LAPI utilise pour écrire les données qui sont décrites par le vecteur d'origine. Le gestionnaire d'en-tête est utilisé pour spécifier l'adresse de la description de vecteur pour l'écriture des données, ce qui élimine la nécessité de connaître la description de la tâche d'origine lorsque le sous-programme est appelé. Le gestionnaire d'en-tête est appelé à l'arrivée du premier paquet de données à la cible.

Vous pouvez également fournir un gestionnaire d'exécution. Le gestionnaire d'en-tête fournit des informations supplémentaires à LAPI sur la distribution des messages, telles que le gestionnaire d'exécution. Vous pouvez également spécifier un paramètre de gestionnaire d'exécution à partir du gestionnaire d'en-tête. LAPI transmet les informations au gestionnaire d'exécution lors de l'exécution.

A l'exception de l'adresse renvoyée par le gestionnaire d'exécution, l'utilisation des compteurs, des gestionnaires d'en-tête et des gestionnaires d'exécution dans LAPI_Amsendv est identique à celle de LAPI_Amsend. Dans les deux cas, le gestionnaire d'en-tête utilisateur renvoie les informations utilisées par LAPI pour écrire sur la cible. Pour plus d'informations, voir LAPI_Amsend . Cette section présente des informations spécifiques à la version vectorielle de l'appel (LAPI_Amsendv).

Les vecteurs LAPI sont des structures de type lapi_vec_t, définies comme suit:
typedef struct  {
    lapi_vectype_t  vec_type;
    uint            num_vecs;
    void            **info;
    ulong           *len;
} lapi_vec_t;
type_vecteur est une énumération qui décrit le type de transfert de vecteur, qui peut être: LAPI_GEN_GENERIC, LAPI_GEN_IOVECTORou LAPI_GEN_STRIDED_XFER.
Pour les transferts de type LAPI_GEN_GENERIC et LAPI_GEN_IOVECTOR, les zones sont utilisées comme suit:
Num_vecs
Indique le nombre de vecteurs de données à transférer. Chaque vecteur de données est défini par une adresse de base et une longueur de données.
info
Est le tableau d'adresses.
longueur
Est le tableau des longueurs de données.
Par exemple, considérons la description de vecteur suivante:
vec_type = LAPI_GEN_IOVECTOR
num_vecs = 3
info     = {addr_0, addr_1, addr_2}
len      = {len_0, len_1, len_2}
Du côté de l'origine, cet exemple indique à LAPI de lire len_0 octets à partir de addr_0, len_1 octets de addr_1et len_2 octets de addr_2. En tant que vecteur cible, cet exemple indique à LAPI d'écrire len_0 octets à addr_0, len_1 octets à addr_1et len_2 octets à addr_2.

Rappelez-vous que les transferts de vecteurs nécessitent une origine et un vecteur cible. Pour les appels LAPI_Amsendv , le vecteur d'origine est transmis à l'appel API sur la tâche d'origine. L'adresse du vecteur cible est renvoyée par le gestionnaire d'en-tête.

Pour les transferts de type LAPI_GEN_GENERIC, la description du vecteur cible doit également être de type LAPI_GEN_GENERIC. Le contenu des tableaux Informations et Len est illimité dans le cas générique ; le nombre de vecteurs et la longueur des vecteurs sur l'origine et la cible n'ont pas besoin d'être identiques. Dans ce cas, LAPI transfère un nombre donné d'octets dans des mémoires tampon non contiguës spécifiées par le vecteur d'origine vers un ensemble de tampons non contigus spécifié par le vecteur cible.

Si la somme des longueurs de données vectorielles cible (par exemple TGT_LEN) est inférieure à la somme des longueurs de données vectorielles d'origine (par exemple ORG_LEN), seuls les TGT_LEN premiers octets des mémoires tampon d'origine sont transférés et les octets restants sont supprimés. Si TGT_LEN est supérieur à ORG_LEN, tous les octets ORG_LEN sont transférés. Prenons l'exemple suivant :
Origin_vector: {
    num_vecs = 3;
    info     = {orgaddr_0, orgaddr_1, orgaddr_2};
    len      = {5, 10, 5}
}

Target_vector: {
    num_vecs = 4;
    info     = {tgtaddr_0, tgtaddr_1, tgtaddr_2, tgtaddr_3};
    len      = {12, 2, 4, 2}
}
LAPI copie les données comme suit:
  1. 5 octets de orgaddr_0 à tgtaddr_0 (laisse 7 octets d'espace à un décalage de 5 octets à partir de tgtaddr_0)
  2. 7 octets de orgaddr_1 à l'espace restant dans tgtaddr_0 (laisse 3 octets de données à transférer depuis orgaddr_1)
  3. 2 octets de orgaddr_1 à tgtaddr_1 (laisse un octet à un transfert à partir de orgaddr_1)
  4. 1 octet de orgaddr_1 suivi de 3 octets de orgaddr_2 vers tgt_addr_2 (laisse 3 octets à transférer à partir de orgaddr_2)
  5. 2 octets de orgaddr_2 à tgtaddr_3
LAPI copie les données de l'origine jusqu'à ce que l'espace décrit par la cible soit rempli. Par exemple :
Origin_vector: {
    num_vecs = 1;
    info     = {orgaddr_0};
    len      = {20}
}

Target_vector: {
    num_vecs = 2;
    info     = {tgtaddr_0, tgtaddr_1};
    len      = {5, 10}
}
LAPI copie 5 octets de orgaddr_0 vers tgtaddr_0 et les 10 octets suivants de orgaddr_0 vers tgtaddr_1. Les 5 octets restants de orgaddr_0 ne seront pas copiés.
Pour les transferts de type LAPI_GEN_IOVECTOR, les longueurs des vecteurs doivent correspondre et la description du vecteur cible doit correspondre à la description du vecteur d'origine. Plus précisément, la description du vecteur cible doit:
  • avoir également le type LAPI_GEN_IOVECTOR
  • Avoir le même Num_vecs que le vecteur d'origine
  • Initialisez le tableau d'informations avec les adresses Num_vecs dans l'espace adresse cible. Pour les vecteurs LAPI origin_vecteur et target_vecteurs décrits de la même manière que l'exemple ci-dessus, les données sont copiées comme suit:
    1. transférer origin_vector.len[ 0 ] octets de l'adresse origin_vector.info[ 0 ] vers l'adresse target_vector.info[ 0 ]
    2. transfert de origin_vector.len[ 1 ] octets de l'adresse origin_vector.info[ 1 ] à l'adresse target_vector.info[ 1 ]
    3. transfert de origin_vector.len[n] octets de l'adresse à origin_vector.info[n] vers l'adresse à target_vector.info[n], pour n = 2 vers n = [num_vecs-3 ]
    4. transfer origin_vector.len[num_vecs-2 ] octets de l'adresse origin_vector.info[num_vecs-2 ] à l'adresse target_vector.info[num_vecs-2 ]
    5. copy origin_vector.len[nombre_vecs-1 ] octets à partir de l'adresse origin_vector.info[nombre_vecs-1 ] vers l'adresse target_vector.info[nombre_vecs-1 ]

Transferts vectoriels rayés

Pour les transferts de type LAPI_GEN_STRIDED_XFER, la description du vecteur cible doit correspondre à la description du vecteur d'origine. Au lieu de spécifier l'ensemble de paires d'adresses et de longueur, le tableau Informations des vecteurs d'origine et de cible est utilisé pour spécifier un "modèle" de bloc de données, consistant en une adresse de base, une taille de bloc et une stride. LAPI s'attend donc à ce que le tableau Informations contienne trois entiers. Le premier entier contient l'adresse de base, le second entier contient la taille de bloc à copier et le troisième entier contient la bande d'octets. Dans ce cas, Num_vecs indique le nombre de blocs de données que LAPI doit copier, où le premier bloc commence à l'adresse de base. Le nombre d'octets à copier dans chaque bloc est donné par la taille de bloc et l'adresse de départ pour tous, mais le premier bloc est donné par l'adresse précédente + stride. La quantité totale de données à copier sera num_vecs*taille_bloc. Prenons l'exemple suivant :
Origin_vector {
    num_vecs = 3;
    info     = {orgaddr, 5, 8}
}
En fonction de cette description, LAPI transfère 5 octets d'orgaddr, 5 octets de orgaddr+8 et 5 octets à partir de orgaddr+16.

Coordonnées de la téléconférence

Comme indiqué ci-dessus, le comportement des compteurs et des gestionnaires dans LAPI_Amsendv est presque identique à celui de LAPI_Amsend. Un court résumé de ce comportement est fourni ici. Pour plus d'informations, voir la description de LAPI_Amsend .

Il s'agit d'un appel non bloquant. La tâche appelante ne peut pas modifier les données Uhc (en-tête d'origine) et Org_vec jusqu'à ce que l'achèvement à l'origine soit signalé par l'incrémentation de Org_cntr . La tâche appelante ne peut pas supposer que la structure Org_vec peut être modifiée avant l'incrémentation du compteur d'origine. La structure (de type lapi_vec_t) renvoyée par le gestionnaire d'en-tête ne peut pas être modifiée avant que le compteur cible ait été incrémenté. De plus, si un gestionnaire d'achèvement est spécifié, il peut s'exécuter de manière asynchrone et ne peut être supposé être terminé qu'après les incréments de compteur cible (sur la cible) ou les incréments du compteur d'achèvement (à l'origine).

La longueur de l'en-tête spécifié par l'utilisateur (Uhdr_len) est limitée par la valeur maximale spécifiée par l'implémentation MAX_UHDR_SZ. Uhdr_len doit être un multiple de la taille du mot double du processeur. Pour obtenir la meilleure bande passante, Uhdr_len doit être le plus petit possible.

Si l'exigence suivante n'est pas remplie, une condition d'erreur se produit:
  • Si un vecteur strié est transféré, la taille de chaque bloc ne doit pas être supérieure à la taille de segment en octets.

LAPI ne vérifie pas les régions qui se chevauchent entre les vecteurs, soit à l'origine, soit à la cible. Si les régions qui se chevauchent existent sur le côté cible, le contenu de la mémoire tampon cible n'est pas défini après l'opération.

Paramètres

Hndl
Indique le descripteur LAPI.
Tgt
Indique l'ID tâche de la tâche cible. La valeur de ce paramètre doit être comprise dans la plage 0 < = tgt < NUM_TASKS.
Hdr_hdl
Pointe vers la fonction de gestionnaire d'en-tête distant à appeler sur la cible. La valeur de ce paramètre peut prendre un descripteur d'adresse précédemment enregistré à l'aide du mécanisme LAPI_Addr_set/LAPI_Addr_get . La valeur de ce paramètre ne peut pas être NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN).
Uhc
Indique le pointeur vers l'en-tête local (liste de paramètres) transmis à la fonction de gestionnaire. Si uhdr_len est 0, la valeur de ce paramètre peut être NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN).
Uhdr_len
Indique la longueur de l'en-tête de l'utilisateur. La valeur de ce paramètre doit être un multiple de la taille de mot double du processeur dans la plage 0 < = uhdr_len < = MAX_UHDR_SZ.
Org_vec
Pointe vers le vecteur d'origine.
Entrée-sortie
Tgt_cntr
Indique l'adresse du compteur cible. Le compteur cible est incrémenté lorsque le gestionnaire d'achèvement (si spécifié) est terminé ou après l'achèvement du transfert de données. Si la valeur de ce paramètre est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN), le compteur cible n'est pas mis à jour.
Org_cntr
Indique l'adresse du compteur d'origine (en C) ou le compteur d'origine (dans FORTRAN). Le compteur d'origine est incrémenté lorsque les données sont copiées hors de l'adresse d'origine (en C) ou de l'origine (dans FORTRAN). Si la valeur de ce paramètre est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN), le compteur d'origine n'est pas mis à jour.
Cmpl_cntr
Indique le compteur à l'origine qui signifie l'achèvement du gestionnaire d'achèvement. Il est mis à jour une fois le gestionnaire d'achèvement terminé. Si aucun gestionnaire d'achèvement n'est spécifié, le compteur est incrémenté à la fin de la distribution des messages. Si la valeur de ce paramètre est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN), le compteur d'achèvement n'est pas mis à jour.
Sortie
Ierror
Indique un code retour FORTRAN. C'est toujours le dernier paramètre.

C Exemples

  1. Pour envoyer un LAPI_GEN_IOVECTOR à l'aide de messages actifs:
    
    /* header handler routine to execute on target task */
    lapi_vec_t *hdr_hndlr(lapi_handle_t *handle, void *uhdr, uint *uhdr_len, 
                          ulong *len_vec[ ], compl_hndlr_t **completion_handler, 
    		      void **user_info)
    {
         /* set completion handler pointer and other info */
          
         /* set up the vector to return to LAPI                                */
         /* for a LAPI_GEN_IOVECTOR: num_vecs, vec_type, and len must all have */ 
         /* the same values as the origin vector.  The info array should       */
         /* contain the buffer addresses for LAPI to write the data            */
         vec->num_vecs = NUM_VECS;
         vec->vec_type = LAPI_GEN_IOVECTOR;
         vec->len      = (unsigned long *)malloc(NUM_VECS*sizeof(unsigned long));
         vec->info     = (void **) malloc(NUM_VECS*sizeof(void *));
         for( i=0; i < NUM_VECS; i++ ) {
             vec->info[i] = (void *) &data_buffer[i];
             vec->len[i]  = (unsigned long)(sizeof(int));
         }
          
         return vec;
    }
          
    {
         
         .	   
         .
         .
    
         void        *hdr_hndlr_list[NUM_TASKS]; /* table of remote header handlers */
         lapi_vec_t  *vec;                       /* data for data transfer          */
          
          
         vec->num_vecs = NUM_VECS;
         vec->vec_type = LAPI_GEN_IOVECTOR;
         vec->len      = (unsigned long *) malloc(NUM_VECS*sizeof(unsigned long));
         vec->info     = (void **) malloc(NUM_VECS*sizeof(void *));
          
         /* each vec->info[i] gets a base address                                   */
         /* each vec->len[i] gets the number of bytes to transfer from vec->info[i] */
          
         LAPI_Amsendv(hndl, tgt, (void *) hdr_hdl_list[buddy], NULL, 0, vec, 
                      tgt_cntr, org_cntr, cmpl_cntr);
          
         /* data will be copied as follows:                    */
         /* len[0] bytes of data starting from address info[0] */
         /* len[1] bytes of data starting from address info[1] */
         .	   
         .
         .
         /* len[NUM_VECS-1] bytes of data starting from address info[NUM_VECS-1] */
                
    }
    L'exemple ci-dessus peut également illustrer le type LAPI_GEN_GENERIC , avec les modifications suivantes:
    • Les deux vecteurs auraient besoin de LAPI_GEN_GENERIC comme vec_type.
    • Il n'existe aucune restriction quant à la symétrie du nombre de vecteurs et de longueurs entre l'origine et les côtés cibles.
  2. Pour envoyer un LAPI_STRIDED_VECTOR à l'aide de messages actifs:
    
    /* header handler routine to execute on target task */
    lapi_vec_t *hdr_hndlr(lapi_handle_t *handle, void *uhdr, uint *uhdr_len, 
                          ulong *len_vec[ ], compl_hndlr_t **completion_handler, 
    		      void **user_info)
    {
          
         int block_size;            /* block size */
         int data_size;             /* stride     */
         .      
         .
         .      
         vec->num_vecs = NUM_VECS;     /* NUM_VECS = number of vectors to transfer */ 
                                       /* must match that of the origin vector     */
         vec->vec_type = LAPI_GEN_STRIDED_XFER;           /* same as origin vector */
              
         /* see comments in origin vector setup for a description of how data      */
         /* will be copied based on these settings.                                */
         vec->info[0]  = buffer_address; /* starting address for data copy         */
         vec->info[1]  = block_size;     /* bytes of data to copy                  */
         vec->info[2]  = stride;         /* distance from copy block to copy block */
         .      
         .
         .      
         return vec;
          
    }
                
    {
          .     
          .
          .
          lapi_vec_t *vec;                                   /* data for data transfer */
            
          vec->num_vecs = NUM_VECS;        /* NUM_VECS = number of vectors to transfer */ 
                                           /* must match that of the target vector     */
          vec->vec_type = LAPI_GEN_STRIDED_XFER;          /* same as target vector     */
             
          vec->info[0]  = buffer_address;    /* starting address for data copy         */
          vec->info[1]  = block_size;        /* bytes of data to copy                  */
          vec->info[2]  = stride;            /* distance from copy block to copy block */
          /* data will be copied as follows:                                           */
          /* block_size bytes will be copied from buffer_address                       */
          /* block_size bytes will be copied from buffer_address+stride                */
          /* block_size bytes will be copied from buffer_address+(2*stride)            */
          /* block_size bytes will be copied from buffer_address+(3*stride)            */
          .          
          .
          .   
          /* block_size bytes will be copied from buffer_address+((NUM_VECS-1)*stride) */
          .      
          .    
          .      
          /* if uhdr isn't used, uhdr should be NULL and uhdr_len should be 0          */
          /* tgt_cntr, org_cntr and cmpl_cntr can all be NULL                          */
          LAPI_Amsendv(hndl, tgt, (void *) hdr_hdl_list[buddy], uhdr, uhdr_len, 
                       vec, tgt_cntr, org_cntr, cmpl_cntr);
         .      
         .
         .
         
    }

Pour des exemples complets, voir les exemples de programmes fournis avec LAPI.

Valeurs renvoyées

LAPI_SUCCESS
Indique que l'appel de fonction a abouti.
LAPI_ERR_HDR_HNDLR_NULL
Indique que le hdr_hdl transmis est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN).
LAPI_ERR_HNDL_INVALID
Indique que le Hndl transmis n'est pas valide (non initialisé ou à l'état arrêté).
LAPI_ERR_ORG_EXTENT
Indique que l'extension de org_vec(stride * num_vecs) est supérieure à la valeur de la constante LAPI LAPI_MAX_MSG_SZ.
LAPI_ERR_ORG_STRIDE
Indique que la segmentation Org_vec est inférieure à bloc.
ADRESSE_ERR_ORG_ADRESSE_VECTEUR_ORDINATEUR
Indique que org_vec->info [ i ] est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN), mais que sa longueur (org_vec->len [ i ]) n'est pas 0.
LAPI_ERR_ORG_VEC_LEN
Indique que la somme de org_vec->len est supérieure à la valeur de la constante LAPI LAPI_MAX_MSG_SZ.
LAPI_ERR_ORG_VEC_NULL
Indique que org_vec est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN).
LAPI_ERR_ORG_VEC_TYPE
Indique que Org_vec->Type_vecteur n'est pas valide.
LAPI_ERR_STRIDE_ORG_VEC_ADDR_NULL
Indique que l'adresse de vecteur segmentée org_vec->info[ 0 ] est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN).
ERR_ERR_TGT
Indique que le Tgt transmis ne correspond pas à la plage de tâches définie dans le travail.
LAPI_ERR_TGT_PURGÉ
Indique que la sous-routine a été renvoyée tôt car LAPI_Purge_totask() a été appelé.
LAPI_ERR_UHDR_LEN
Indique que la valeur Uhdr_len transmise est supérieure à MAX_UHDR_SZ ou qu'elle n'est pas un multiple de la taille du mot de passe du processeur.
LAPI_ERR_UHDR_NULL
Indique que le uhdr transmis est NULL (en C) ou LAPI_ADDR_NULL (en FORTRAN), mais que uhdr_len n'est pas 0.

Emplacement

/usr/lib/liblapi_r.a