LAPI_Amsendv Subroutine
Purpose
Transfers a user vector to a remote task, obtaining the target address on the remote task from a user-specified header handler.
Library
Availability Library (liblapi_r.a)
C Syntax
#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 Syntax
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
Description
Type of call: point-to-point communication (non-blocking)
LAPI_Amsendv is the vector-based version of the LAPI_Amsend call. You can use it to specify multi-dimensional and non-contiguous descriptions of the data to transfer. Whereas regular LAPI calls allow the specification of a single data buffer address and length, the vector versions allow the specification of a vector of address and length combinations. Additional information is allowed in the data description on the origin task and the target task.
Use this subroutine to transfer a vector of data to a target task, when you want a handler to run on the target task before message delivery begins or after message delivery completes.
To use LAPI_Amsendv, you must provide a header handler, which returns the address of the target vector description that LAPI uses to write the data that is described by the origin vector. The header handler is used to specify the address of the vector description for writing the data, which eliminates the need to know the description on the origin task when the subroutine is called. The header handler is called upon arrival of the first data packet at the target.
Optionally, you can also provide a completion handler. The header handler provides additional information to LAPI about the message delivery, such as the completion handler. You can also specify a completion handler parameter from within the header handler. LAPI passes the information to the completion handler at execution.
With the exception of the address that is returned by the completion handler, the use of counters, header handlers, and completion handlers in LAPI_Amsendv is identical to that of LAPI_Amsend. In both cases, the user header handler returns information that LAPI uses for writing at the target. See LAPI_Amsend for more information. This section presents information that is specific to the vector version of the call (LAPI_Amsendv).
typedef struct {
lapi_vectype_t vec_type;
uint num_vecs;
void **info;
ulong *len;
} lapi_vec_t;
vec_type is an
enumeration that describes the type of vector transfer, which can
be: LAPI_GEN_GENERIC, LAPI_GEN_IOVECTOR,
or LAPI_GEN_STRIDED_XFER. - num_vecs
- indicates the number of data vectors to transfer. Each data vector is defined by a base address and data length.
- info
- is the array of addresses.
- len
- is the array of data lengths.
vec_type = LAPI_GEN_IOVECTOR
num_vecs = 3
info = {addr_0, addr_1, addr_2}
len = {len_0, len_1, len_2}
On the origin side, this
example would tell LAPI to read len_0 bytes from addr_0, len_1 bytes
from addr_1, and len_2 bytes from addr_2. As a target vector, this
example would tell LAPI to write len_0 bytes to addr_0, len_1 bytes
to addr_1, and len_2 bytes to addr_2.Recall that vector transfers require an origin and target vector. For LAPI_Amsendv calls, the origin vector is passed to the API call on the origin task. The address of the target vector is returned by the header handler.
For transfers of type LAPI_GEN_GENERIC, the target vector description must also have type LAPI_GEN_GENERIC. The contents of the info and len arrays are unrestricted in the generic case; the number of vectors and the length of vectors on the origin and target do not need to match. In this case, LAPI transfers a given number of bytes in noncontiguous buffers specified by the origin vector to a set of noncontiguous buffers specified by the target vector.
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 copies data as follows: - 5 bytes from orgaddr_0 to tgtaddr_0 (leaves 7 bytes of space at a 5-byte offset from tgtaddr_0)
- 7 bytes from orgaddr_1 to remaining space in tgtaddr_0 (leaves 3 bytes of data to transfer from orgaddr_1)
- 2 bytes from orgaddr_1 to tgtaddr_1 (leaves 1 byte to transfer from orgaddr_1)
- 1 byte from orgaddr_1 followed by 3 bytes from orgaddr_2 to tgt_addr_2 (leaves 3 bytes to transfer from orgaddr_2)
- 2 bytes from orgaddr_2 to tgtaddr_3
Origin_vector: {
num_vecs = 1;
info = {orgaddr_0};
len = {20}
}
Target_vector: {
num_vecs = 2;
info = {tgtaddr_0, tgtaddr_1};
len = {5, 10}
}
LAPI will copy 5 bytes from orgaddr_0 to tgtaddr_0 and
the next 10 bytes from orgaddr_0 to tgtaddr_1. The remaining 5 bytes
from orgaddr_0 will not be copied.- also have type LAPI_GEN_IOVECTOR
- have the same num_vecs as the origin vector
- initialize the info array with num_vecs addresses
in the target address space. For LAPI vectors origin_vector and
target_vector described similarly to the example above, data is copied
as follows:
- transfer origin_vector.len[0] bytes from the address at origin_vector.info[0] to the address at target_vector.info[0]
- transfer origin_vector.len[1] bytes from the address at origin_vector.info[1] to the address at target_vector.info[1]
- transfer origin_vector.len[n] bytes from the address at origin_vector.info[n] to the address at target_vector.info[n], for n = 2 to n = [num_vecs-3]
- transfer origin_vector.len[num_vecs-2] bytes from the address at origin_vector.info[num_vecs-2] to the address at target_vector.info[num_vecs-2]
- copy origin_vector.len[num_vecs-1] bytes from the address at origin_vector.info[num_vecs-1] to the address at target_vector.info[num_vecs-1]
Strided vector transfers
Origin_vector {
num_vecs = 3;
info = {orgaddr, 5, 8}
}
Based on this description, LAPI will transfer 5 bytes
from orgaddr, 5 bytes from orgaddr+8 and 5 bytes from orgaddr+16.Call details
As mentioned above, counter and handler behavior in LAPI_Amsendv is nearly identical to that of LAPI_Amsend. A short summary of that behavior is provided here. See the LAPI_Amsend description for full details.
This is a non-blocking call. The calling task cannot change the uhdr (origin header) and org_vec data until completion at the origin is signaled by the org_cntr being incremented. The calling task cannot assume that the org_vec structure can be changed before the origin counter is incremented. The structure (of type lapi_vec_t) that is returned by the header handler cannot be modified before the target counter has been incremented. Also, if a completion handler is specified, it may execute asynchronously, and can only be assumed to have completed after the target counter increments (on the target) or the completion counter increments (at the origin).
The length of the user-specified header (uhdr_len) is constrained by the implementation-specified maximum value MAX_UHDR_SZ. uhdr_len must be a multiple of the processor's doubleword size. To get the best bandwidth, uhdr_len should be as small as possible.
- If a strided vector is being transferred, the size of each block must not be greater than the stride size in bytes.
LAPI does not check for any overlapping regions among vectors either at the origin or the target. If the overlapping regions exist on the target side, the contents of the target buffer are undefined after the operation.
Parameters
- hndl
- Specifies the LAPI handle.
- tgt
- Specifies the task ID of the target task. The value of this parameter must be in the range 0 <= tgt < NUM_TASKS.
- hdr_hdl
- Points to the remote header handler function to be invoked at the target. The value of this parameter can take an address handle that had been previously registered using the LAPI_Addr_set/LAPI_Addr_get mechanism. The value of this parameter cannot be NULL (in C) or LAPI_ADDR_NULL (in FORTRAN).
- uhdr
- Specifies the pointer to the local header (parameter list) that is passed to the handler function. If uhdr_len is 0, The value of this parameter can be NULL (in C) or LAPI_ADDR_NULL (in FORTRAN).
- uhdr_len
- Specifies the length of the user's header. The value of this parameter must be a multiple of the processor's doubleword size in the range 0 <= uhdr_len <= MAX_UHDR_SZ.
- org_vec
- Points to the origin vector.
- INPUT/OUTPUT
- tgt_cntr
- Specifies the target counter address. The target counter is incremented after the completion handler (if specified) completes or after the completion of data transfer. If the value of this parameter is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN), the target counter is not updated.
- org_cntr
- Specifies the origin counter address (in C) or the origin counter (in FORTRAN). The origin counter is incremented after data is copied out of the origin address (in C) or the origin (in FORTRAN). If the value of this parameter is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN), the origin counter is not updated.
- cmpl_cntr
- Specifies the counter at the origin that signifies completion of the completion handler. It is updated once the completion handler completes. If no completion handler is specified, the counter is incremented at the completion of message delivery. If the value of this parameter is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN), the completion counter is not updated.
- OUTPUT
- ierror
- Specifies a FORTRAN return code. This is always the last parameter.
C Examples
- To send a LAPI_GEN_IOVECTOR using active
messages:
The above example could also illustrate the LAPI_GEN_GENERIC type, with the following modifications:/* 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] */ }
- Both vectors would need LAPI_GEN_GENERIC as the vec_type.
- There are no restrictions on symmetry of number of vectors and lengths between the origin and target sides.
- To send a LAPI_STRIDED_VECTOR using
active messages:
/* 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); . . . }
For complete examples, see the sample programs shipped with LAPI.
Return Values
- LAPI_SUCCESS
- Indicates that the function call completed successfully.
- LAPI_ERR_HDR_HNDLR_NULL
- Indicates that the hdr_hdl passed in is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN).
- LAPI_ERR_HNDL_INVALID
- Indicates that the hndl passed in is not valid (not initialized or in terminated state).
- LAPI_ERR_ORG_EXTENT
- Indicates that the org_vec's extent (stride * num_vecs) is greater than the value of LAPI constant LAPI_MAX_MSG_SZ.
- LAPI_ERR_ORG_STRIDE
- Indicates that the org_vec stride is less than block.
- LAPI_ERR_ORG_VEC_ADDR
- Indicates that the org_vec->info[i] is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN), but its length (org_vec->len[i]) is not 0.
- LAPI_ERR_ORG_VEC_LEN
- Indicates that the sum of org_vec->len is greater than the value of LAPI constant LAPI_MAX_MSG_SZ.
- LAPI_ERR_ORG_VEC_NULL
- Indicates that org_vec is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN).
- LAPI_ERR_ORG_VEC_TYPE
- Indicates that the org_vec->vec_type is not valid.
- LAPI_ERR_STRIDE_ORG_VEC_ADDR_NULL
- Indicates that the strided vector address org_vec->info[0] is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN).
- LAPI_ERR_TGT
- Indicates that the tgt passed in is outside the range of tasks defined in the job.
- LAPI_ERR_TGT_PURGED
- Indicates that the subroutine returned early because LAPI_Purge_totask() was called.
- LAPI_ERR_UHDR_LEN
- Indicates that the uhdr_len value passed in is greater than MAX_UHDR_SZ or is not a multiple of the processor's doubleword size.
- LAPI_ERR_UHDR_NULL
- Indicates that the uhdr passed in is NULL (in C) or LAPI_ADDR_NULL (in FORTRAN), but uhdr_len is not 0.
Location
- /usr/lib/liblapi_r.a