LAPI_Amsendv 子例程

用途

将用户向量传输到远程任务,从而从用户指定的头处理程序获取远程任务上的目标地址。

可用性库 (liblapi_r.a)

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; 

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
 

描述

Type of call: 点到点通信 (非阻塞)

LAPI_Amsendv 是基于向量的 LAPI_Amsend 调用版本。 您可以使用它来指定要传输的数据的多维和非连续描述。 而常规的 LAPI 调用允许指定单个数据缓冲区地址和长度,而向量版本允许指定地址和长度组合的向量。 在有关源任务和目标任务的数据描述中允许使用其他信息。

当您希望处理程序在消息传递开始之前或在消息传递完成之后在目标任务上运行时,使用此子例程将数据向量传送到目标任务。

要使用 LAPI_Amsendv,必须提供头处理程序,该处理程序返回 LAPI 用于写入由源向量描述的数据的目标向量描述的地址。 头处理程序用于指定用于编写数据的向量描述的地址,这样就不需要在调用子例程时知道源任务上的描述。 头处理程序在第一个数据包到达目标时被调用。

(可选) 您还可以提供完成处理程序。 头处理程序向 LAPI 提供有关消息传递的其他信息,例如完成处理程序。 您还可以从头处理程序中指定完成处理程序参数。 LAPI 在执行时将信息传递到完成处理程序。

除了完成处理程序返回的地址之外,在 LAPI_Amsendv 中使用的计数器,头处理程序和完成处理程序与 LAPI_Amsend完全相同。 在这两种情况下,用户头处理程序都返回 LAPI 用于在目标处进行写入的信息。 请参阅 LAPI_Amsend 以获取更多信息。 本部分提供了特定于调用的向量版本 (LAPI_Amsendv) 的信息。

LAPI 向量是类型为 lapi_vec_t的结构,定义如下:
typedef struct  {
    lapi_vectype_t  vec_type;
    uint            num_vecs;
    void            **info;
    ulong           *len;
} lapi_vec_t;
vec_type 是用于描述向量传输类型的枚举,可以是: LAPI_GEN_GENERICLAPI_GEN_IOVECTORLAPI_GEN_STRIDED_XFER
对于类型为 LAPI_GEN_GENERICLAPI_GEN_IOVECTOR的传输,将按如下所示使用这些字段:
努 _vecs
指示要传输的数据向量数。 每个数据向量由一个基地址和数据长度定义。
信息
是地址数组。
len
是数据长度的数组。
例如,请考虑以下向量描述:
vec_type = LAPI_GEN_IOVECTOR
num_vecs = 3
info     = {addr_0, addr_1, addr_2}
len      = {len_0, len_1, len_2}
在源端,此示例将告知 LAPI 从 addr_0读取 len_0 个字节,从 addr_1读取 len_1 个字节,从 addr_2读取 len_2 个字节。 作为目标向量,此示例将告知 LAPI 将 len_0 个字节写入 addr_0,将 len_1 个字节写入 addr_1,并将 len_2 个字节写入 addr_2。

请记住,向量传输需要源和目标向量。 对于 LAPI_Amsendv 调用,源向量将传递到源任务上的 API 调用。 目标向量的地址将由头处理程序返回。

对于类型为 LAPI_GEN_GENERIC的传输,目标向量描述还必须具有类型 LAPI_GEN_GENERIC。 在一般情况下, 信息 数组的内容是无限制的; 源和目标上的向量数量和长度不需要匹配。 在此情况下, LAPI 会将源向量指定的非连续缓冲区中的给定字节数传送到目标向量指定的一组非连续缓冲区。

如果目标向量数据长度之和 (例如 TGT_LEN) 小于源向量数据长度之和 (例如 ORG_LEN) ,那么将仅传输来自源缓冲区的前 TGT_LEN 字节,并且将废弃其余字节。 如果 TGT_LEN 大于 ORG_LEN,那么将传输所有 ORG_LEN 字节。 请考虑以下示例:
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 按如下所示复制数据:
  1. 5 从 orgaddr_0 到 tgtaddr_0 的 5 个字节 (使 7 个字节的空间从 tgtaddr_0偏移 5 为 5 个字节)
  2. 7 从 orgaddr_1 到 tgtaddr_0 中剩余空间的 7 个字节 (留下 3 个字节的数据从 orgaddr_1进行传输)
  3. 2 从 orgaddr_1 到 tgtaddr_1 的 2 个字节 (从 orgaddr_1传输 1 个字节)
  4. 1 1 个字节 (从 orgaddr_1 开始) ,后跟 3 个字节 (从 orgaddr_2 到 tgt_addr_2 ) (从 orgaddr_2开始传输 3 个字节)
  5. 2 从 orgaddr_2 到 tgtaddr_3 的 2 个字节
LAPI 将从源复制数据,直到目标所描述的空间被填满为止。 例如:
Origin_vector: {
    num_vecs = 1;
    info     = {orgaddr_0};
    len      = {20}
}

Target_vector: {
    num_vecs = 2;
    info     = {tgtaddr_0, tgtaddr_1};
    len      = {5, 10}
}
LAPI 会将 5 个字节从 orgaddr_0 复制到 tgtaddr_0 ,并将接下来的 10 个字节从 orgaddr_0 复制到 tgtaddr_1。 将不会复制来自 orgaddr_0 的剩余 5 个字节。
对于类型为 LAPI_GEN_IOVECTOR的传输,向量的长度必须匹配,并且目标向量描述必须与源向量描述匹配。 更具体地说,目标向量描述必须:
  • 还具有类型 LAPI_GEN_IOVECTOR
  • 具有与源向量相同的 努 _vecs
  • 使用目标地址空间中的 努 _vecs 地址初始化信息数组。 对于与以上示例类似的 LAPI 向量 origin_vector 和 target_vector ,数据复制如下:
    1. 将 origin_vector.len[0] 字节从位于 origin_vector.info[0] 的地址传输到位于 target_vector.info[0] 的地址
    2. 将 origin_vector.len[1] 字节从位于 origin_vector.info[1] 的地址传输到位于 target_vector.info[1] 的地址
    3. 将 origin_vector.len[n] 字节从位于 origin_vector.info[n] 的地址传输到位于 target_vector.info[n] 的地址,用于 n = 2n = [num_vecs-3]
    4. 将 origin_vector.len[num_vecs-2] 字节从位于 origin_vector.info[num_vecs-2] 的地址传输到位于 target_vector.info[num_vecs-2] 的地址
    5. 将 origin_vector.len[num_vecs-1] 字节从位于 origin_vector.info[num_vecs-1] 的地址复制到位于 target_vector.info[num_vecs-1] 的地址

带删除线的向量传输

对于类型为 LAPI_GEN_STRIDED_XFER的传输,目标向量描述必须与源向量描述匹配。 源向量和目标向量的 信息 数组用于指定数据块 "模板" ,而不是指定地址和长度对的集合,该数据块 "模板" 由基地址,块大小和删除线组成。 因此, LAPI 期望 信息 数组包含三个整数。 第一个整数包含基本地址,第二个整数包含要复制的块大小,第三个整数包含字节的删除线。 在此情况下, 努 _vecs 指示 LAPI 应该复制的数据块数,其中第一个块以基地址开头。 每个块中要复制的字节数由块大小给出,而除第一个块的起始地址由先前地址 + stride 给出。 要复制的数据总量将为 num_vecs*block_size。 请考虑以下示例:
Origin_vector {
    num_vecs = 3;
    info     = {orgaddr, 5, 8}
}
根据此描述, LAPI 将 5 orgaddr 传输 5 个字节,从 orgaddr+8 传输 5 个字节,从 orgaddr+16传输 5 个字节。

调用详细信息

如上所述, LAPI_Amsendv 中的计数器和处理程序行为几乎与 LAPI_Amsend的行为完全相同。 此处提供了该行为的简短摘要。 请参阅 LAPI_Amsend 描述以获取完整详细信息。

这是一个非阻塞的调用。 调用任务无法更改 乌赫德尔 (源头) 和 奥尔格韦茨 数据,直到在源处完成由 奥尔格-奇特尔 递增的信号表示。 调用任务不能假定 奥尔格韦茨 结构可以在源计数器递增之前进行更改。 在增加目标计数器之前,无法修改头处理程序返回的结构 (类型为 lapi_vec_t)。 此外,如果指定了完成处理程序,那么它可能会异步执行,并且只能假定为在目标计数器增量 (在目标上) 或完成计数器增量 (在源处) 之后完成。

用户指定的头 (uhdr_len) 的长度受到实现指定的最大值 MAX_UHDR_SZ的限制。 uhdr_len 必须是处理器的双单词大小的倍数。 要获得最佳带宽, uhdr_len 应该尽可能地小。

如果不满足以下需求,那么会发生错误情况:
  • 如果正在传输带条纹的向量,那么每个块的大小不得大于带条纹的大小 (以字节为单位)。

LAPI 不会检查源或目标上的向量之间是否有任何重叠区域。 如果目标端存在重叠区域,那么在执行该操作后将取消定义目标缓冲区的内容。

参数

恩德尔
指定 LAPI 句柄。
特格特
指定该目标任务的任务标识。 The value of this parameter must be in the range 0 <= 哥特 < NUM_TASKS.
hdr_hdl
指向要在目标处调用的远程头处理程序函数。 此参数的值可以采用先前使用 LAPI_Addr_set/LAPI_Addr_get 机制注册的地址句柄。 此参数的值不能为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中)。
乌赫德尔
指定一个指向传递给处理程序函数的本地头 (参数列表) 的指针。 如果 uhdr_len0,那么此参数的值可以是 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中)。
uhdr_len
指定用户的头的长度。 The value of this parameter must be a multiple of the processor's doubleword size in the range 0 <= Uhdr_len <= MAX_UHDR_SZ.
奥尔格韦茨
指向源向量。
输入/输出
tgt_cntr
指定目标计数器地址。 在完成处理程序 (如果已指定) 完成或数据传输完成后,目标计数器将递增。 如果此参数的值为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) ,那么不会更新目标计数器。
奥尔格-奇特尔
指定源计数器地址 (以 C 为单位) 或源计数器 (以 FORTRAN 为单位)。 在从源地址 (以 C 为单位) 或源 (以 FORTRAN 为单位) 复制数据后,源计数器将递增。 如果此参数的值为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) ,那么不会更新源计数器。
cmpl_cntr
指定表示完成处理程序完成的源处的计数器。 一旦完成处理程序完成,就会对其进行更新。 如果未指定任何完成处理程序,那么在完成消息传递时计数器将递增。 如果此参数的值为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) ,那么不会更新完成计数器。
输出
国际错误
指定 FORTRAN 返回码。 这始终是最后一个参数。

C 示例

  1. 要使用活动消息发送 LAPI_GEN_IOVECTOR :
    
    /* 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] */
                
    }
    以上示例还可以说明 LAPI_GEN_GENERIC 类型,并进行以下修改:
    • 这两个向量都需要 LAPI_GEN_GENERIC 作为 vec_type。
    • 在原点和目标边之间的向量数量和长度对称方面没有任何限制。
  2. 要使用活动消息发送 LAPI_STRIDED_VECTOR :
    
    /* 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);
         .      
         .
         .
         
    }

有关完整示例,请参阅 LAPI 随附的样本程序。

返回值

LAPI_SUCCESS
指示已成功完成函数调用。
LAPI_ERR_HDR_HNDLR_NULL
指示传入的 hdr_hdl 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中)。
LAPI_ERR_HNDL_INVALID
指示传入的 恩德尔 无效 (未初始化或处于 "已终止" 状态)。
LAPI_ERROR_ORG_EXTENT
指示 org_vec的扩展数据块 (stride * num_vecs) 大于 LAPI 常量 LAPI_MAX_MSG_SZ的值。
LAPI_ERROR_ORG_STRIDE
指示 奥尔格韦茨 stride 小于 block。
LAPI_ERROR_ORG_VEC_ADDR
指示 org_vec->info [i] 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) ,但其长度 (org_vec->len [i]) 不是 0
LAPI_ERROR_ORG_VEC_LEN
指示 org_vec->len 的总和大于 LAPI 常量 LAPI_MAX_MSG_SZ的值。
LAPI_ERROR_ORG_VEC_NULL
指示 org_vec 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中)。
LAPI_ERROR_ORG_VEC_TYPE
指示 " 奥尔格韦茨->向量类型 " 无效。
LAPI_ERR_STRIDE_ORG_VEC_ADDR_NULL
指示条带化向量地址 org_vec->info[0] 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中)。
LAPI_ERR_TGT
指示传入的 特格特 在作业中定义的任务范围之外。
已清除 LAPI_ERR_TGT_CLEAR
指示由于调用了 LAPI_Purge_totask() 而提前返回了子例程。
LAPI_ERR_UHDR_LEN
指示传递的 uhdr_len 值大于 MAX_UHDR_SZ ,或者不是处理器的双字大小的倍数。
LAPI_ERR_UHDR_NULL
指示传入的 uhdr 为 NULL (在 C 中) 或 LAPI_ADDR_NULL (在 FORTRAN 中) ,但 uhdr_len 不是 0

位置

/usr/lib/liblapi_r.a