This C program is an example of transferring noncontiguous data using the LAPI vector transfer function:
/* putv_multi_gen.c
** Example Program showing use of the LAPI vector transfer function.
*/
#include <stdio.h>
#include <assert.h>
#include "lapi.h"
#define MAX_TASKS 4 /* Max tasks in the parallel job */
#define MAX_GLOBAL_ADDR 16 /* Max size of local address table */
#define ARR_SZ 8280000 /* Size of array */
#define NUM_ITER 10 /* Max number of iterations */
#define NUM_TIMES 4
extern double microsecond(); /* defined in the timer library */
int sizes[] = {3,4,9, 16, 30, 64, 128, 171, 256, 353,1000};
lapi_handle_t hndl; /* Handle to the lapi context */
lapi_info_t info_lapi; /* to be passed to LAPI_Init */
int myid, numtasks; /* taskid and numtasks in || job */
#define ROWS 353
#define COLUMNS 3000
char g1[ROWS][COLUMNS]; /* Array which w */
lapi_vec_t org_vec,tgt_vec;
void *g1_addr[MAX_TASKS]; /* Address of g1 of other tasks */
lapi_vec_t *vec_addr[MAX_TASKS]; /* Address of g1 of other tasks */
void *global_addr[MAX_TASKS]; /* Address of global_address tables
** of each task
*/
void *local_addr[MAX_GLOBAL_ADDR]; /* Address of local address table */
lapi_cntr_t c1, c2, c3; /* LAPI counters */
lapi_cntr_t *c1_addr[MAX_TASKS], *c2_addr[MAX_TASKS], *c3_addr[MAX_TASKS];
/* Address of counters on each task */
double results[NUM_TIMES];
/*
** Macros to turn interrupts on and off, and to turn error checking off
*/
#define INTR_ON LAPI_Senv(hndl, INTERRUPT_SET, 1) /* Turn interrupts on*/
#define INTR_OFF LAPI_Senv(hndl, INTERRUPT_SET, 0) /* Turn inter off */
#define INTR_CNT(num) LAPI_Qenv(hndl, 22, &(num))
#define INTR_CNT_OFF LAPI_Senv(hndl, 22, 0)
#define ERR_CHK_OFF LAPI_Senv(hndl, ERROR_CHK, 0) /* Turn error checking off*/
/*
** Function: This measures Putv bandwidth for a given message size by sending
** a message from task 0 to task 1 and returning the message
** from task 1 to task 0.
*/
void
rr_one_way_lat(int cnt)
{
double t0, t1, t1_pr, t1_dpr, diff;
int i, rc, tmp_cntr = 0;
diff = 0.0;
t0 = microsecond();
for (i=0;i<NUM_ITER; i++) {
if (myid == 0) {
//g1[1] = 1024;
rc=LAPI_Putv(hndl, 1, &tgt_vec, &org_vec, c1_addr[1], NULL, NULL);
LAPI_Waitcntr(hndl, &c1, 1, NULL);
} else if (myid == 1) {
LAPI_Waitcntr(hndl, &c1, 1, NULL);
rc=LAPI_Putv(hndl, 0, &tgt_vec, &org_vec, c1_addr[0], NULL, NULL);
}
}
t1 = microsecond();
if (myid == 0) {
results[0] = (t1 - t0)/(2.0 * NUM_ITER);
results[0] = (cnt*cnt*8)/(results[0]);
}
}
/*
** Function: This runs the rr_one_way_lat function for various message sizes
** and prints the results.
*/
void
run_tests(int i)
{
int rc, cnt;
INTR_OFF;
for (cnt=0; cnt < 1; cnt++) {
rr_one_way_lat(i);
}
if (myid == 0)
for(cnt=0; cnt < 1; cnt++)
printf("Putv bandwidth (gen) for %d X %d array = %lf\n", i,i,results[cnt]);
}
/*
** Main function.
** Sets up the LAPI environment, initialized variables, counters, and addresses
** and calls run_tests.
*/
main()
{
int i,j,k,rc, cntr, partner;
uint addr_ptr;
/* Initialize global data structures to 0 */
init_stamp(NULL, NULL);
bzero(g1, sizeof(g1));
bzero(local_addr, sizeof(local_addr));
bzero(global_addr, sizeof(global_addr));
bzero(&info_lapi, sizeof(lapi_info_t));
rc = LAPI_Init(&hndl, &info_lapi); /* Initialize the LAPI library */
assert(rc == 0);
/* Query LAPI library for taskid and number of tasks in job */
rc = LAPI_Qenv(hndl, TASK_ID, &myid);
rc = LAPI_Qenv(hndl, NUM_TASKS, &numtasks);
LAPI_Senv(hndl, ERROR_CHK,0);
if (myid == 0) partner = 1; else partner = 0;
/* Initialize LAPI counters */
rc = LAPI_Setcntr(hndl, &c1, 0);
rc = LAPI_Setcntr(hndl, &c2, 0);
rc = LAPI_Setcntr(hndl, &c3, 0);
/* Fill in local address table */
rc = LAPI_Address(g1, (uint *)&local_addr[0]);
/* Exchange local address table with every task */
rc = LAPI_Address_init(hndl, local_addr, global_addr);
/* Exchange other address of importance to LAPI like g1, and counters */
rc = LAPI_Address_init(hndl, (void *)g1, g1_addr);
rc = LAPI_Address_init(hndl, (void *)&org_vec, (void *)vec_addr);
rc = LAPI_Address_init(hndl, (void *)&c1, (void *)c1_addr);
rc = LAPI_Address_init(hndl, (void *)&c2, (void *)c2_addr);
rc = LAPI_Address_init(hndl, (void *)&c3, (void *)c3_addr);
// ERR_CHK_OFF;
rc = LAPI_Gfence(hndl);
for (k=0; k < 11; k++) {
i = sizes[k];
org_vec.vec_type = LAPI_GEN_IOVECTOR;
org_vec.num_vecs = i;
org_vec.info = (void **) malloc(i * sizeof(void *));
for (j=0;j<i;j++)
org_vec.info[j] = (void *) g1[j];
org_vec.len = (uint *) malloc(i * sizeof(uint));
for (j=0;j<i;j++)
org_vec.len[j] = i*8;
tgt_vec.vec_type = LAPI_GEN_IOVECTOR;
tgt_vec.num_vecs = i;
tgt_vec.info = (void **) malloc(i * sizeof(void *));
for (j=0;j<i;j++)
tgt_vec.info[j] = (void *) (g1_addr[partner] +j*COLUMNS);
tgt_vec.len = (uint *) malloc(i * sizeof(uint));
for (j=0;j<i;j++)
tgt_vec.len[j] = i*8;
run_tests(i); /* Run various LAPI tests */
rc = LAPI_Gfence(hndl);
free(org_vec.info);
free(tgt_vec.info);
}
rc = LAPI_Term(hndl);
}