1
1

Merge pull request #699 from hjelmn/libnbc_fixes

coll/libnbc: rewrite parts of libnbc
Этот коммит содержится в:
Nathan Hjelm 2015-08-10 14:51:42 -06:00
родитель 87db836800 d42e0968b1
Коммит 624a4a0f82
30 изменённых файлов: 3968 добавлений и 2943 удалений

Просмотреть файл

@ -22,7 +22,6 @@
sources = \
coll_libnbc.h \
coll_libnbc_component.c \
coll_libnbc_ireduce_scatter_block.c \
nbc.c \
nbc_internal.h \
libdict/dict.h \
@ -49,6 +48,7 @@ sources = \
nbc_ineighbor_alltoallw.c \
nbc_ireduce.c \
nbc_ireduce_scatter.c \
nbc_ireduce_scatter_block.c \
nbc_iscan.c \
nbc_iscatter.c \
nbc_iscatterv.c \

Просмотреть файл

@ -98,9 +98,16 @@ OBJ_CLASS_DECLARATION(ompi_coll_libnbc_module_t);
typedef ompi_coll_libnbc_module_t NBC_Comminfo;
/* a schedule is basically a pointer to some memory location where the
* schedule array resides */
typedef void* NBC_Schedule;
struct NBC_Schedule {
opal_object_t super;
volatile int size;
volatile int current_round_offset;
char *data;
};
typedef struct NBC_Schedule NBC_Schedule;
OBJ_CLASS_DECLARATION(NBC_Schedule);
struct ompi_coll_libnbc_request_t {
ompi_request_t super;
@ -110,7 +117,7 @@ struct ompi_coll_libnbc_request_t {
volatile int req_count;
ompi_request_t **req_array;
NBC_Comminfo *comminfo;
volatile NBC_Schedule *schedule;
NBC_Schedule *schedule;
void *tmpbuf; /* temporary buffer e.g. used for Reduce */
/* TODO: we should make a handle pointer to a state later (that the user
* can move request handles) */
@ -134,9 +141,9 @@ typedef ompi_coll_libnbc_request_t NBC_Handle;
#define OMPI_COLL_LIBNBC_REQUEST_RETURN(req) \
do { \
OMPI_REQUEST_FINI(&request->super); \
OMPI_REQUEST_FINI(&(req)->super); \
opal_free_list_return (&mca_coll_libnbc_component.requests, \
(opal_free_list_item_t*) req); \
(opal_free_list_item_t*) (req)); \
} while (0)
int ompi_coll_libnbc_progress(void);

Просмотреть файл

@ -239,7 +239,7 @@ ompi_coll_libnbc_progress(void)
OPAL_LIST_FOREACH_SAFE(request, next, &mca_coll_libnbc_component.active_requests,
ompi_coll_libnbc_request_t) {
if (NBC_OK == NBC_Progress(request)) {
if (OMPI_SUCCESS == NBC_Progress(request)) {
/* done, remove and complete */
opal_list_remove_item(&mca_coll_libnbc_component.active_requests,
&request->super.super.super);

Просмотреть файл

@ -1,243 +0,0 @@
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014-2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
*/
#include "nbc_internal.h"
/* an reduce_csttare schedule can not be cached easily because the contents
* ot the recvcount value may change, so a comparison of the address
* would not be sufficient ... we simply do not cache it */
/* binomial reduce to rank 0 followed by a linear scatter ...
*
* Algorithm:
* pairwise exchange
* round r:
* grp = rank % 2^r
* if grp == 0: receive from rank + 2^(r-1) if it exists and reduce value
* if grp == 1: send to rank - 2^(r-1) and exit function
*
* do this for R=log_2(p) rounds
*
*/
int ompi_coll_libnbc_ireduce_scatter_block(void* sendbuf, void* recvbuf, int recvcount, MPI_Datatype datatype,
MPI_Op op, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int peer, rank, maxr, p, r, res, count, offset, firstred;
MPI_Aint ext;
char *redbuf, *sbuf, inplace;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res || 0 == p) { printf("MPI Error in MPI_Comm_size() (%i:%i)\n", res, p); return (MPI_SUCCESS == res) ? MPI_ERR_SIZE : res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res || 0 == ext) { printf("MPI Error in MPI_Type_extent() (%i:%i)\n", res, (int)ext); return (MPI_SUCCESS == res) ? MPI_ERR_SIZE : res; }
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return NBC_OOR; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
maxr = (int)ceil((log((double)p)/LOG2));
count = p * recvcount;
if (0 < count) {
handle->tmpbuf = malloc(ext*count*2);
if(handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
redbuf = ((char*)handle->tmpbuf)+(ext*count);
/* copy data to redbuf if we only have a single node */
if((p==1) && !inplace) {
res = NBC_Copy(sendbuf, count, datatype, redbuf, count, datatype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
}
firstred = 1;
for(r=1; r<=maxr; r++) {
if((rank % (1<<r)) == 0) {
/* we have to receive this round */
peer = rank + (1<<(r-1));
if(peer<p) {
res = NBC_Sched_recv(0, true, count, datatype, peer, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if(firstred) {
/* take reduce data from the sendbuf in the first round -> save copy */
res = NBC_Sched_op(redbuf-(unsigned long)handle->tmpbuf, true, sendbuf, false, 0, true, count, datatype, op, schedule);
firstred = 0;
} else {
/* perform the reduce in my local buffer */
res = NBC_Sched_op(redbuf-(unsigned long)handle->tmpbuf, true, redbuf-(unsigned long)handle->tmpbuf, true, 0, true, count, datatype, op, schedule);
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
} else {
/* we have to send this round */
peer = rank - (1<<(r-1));
if(firstred) {
/* we have to send the senbuf */
res = NBC_Sched_send(sendbuf, false, count, datatype, peer, schedule);
} else {
/* we send an already reduced value from redbuf */
res = NBC_Sched_send(redbuf-(unsigned long)handle->tmpbuf, true, count, datatype, peer, schedule);
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
/* leave the game */
break;
}
}
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
/* rank 0 is root and sends - all others receive */
if(rank != 0) {
res = NBC_Sched_recv(recvbuf, false, recvcount, datatype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
if(rank == 0) {
offset = 0;
for(r=1;r<p;r++) {
offset += recvcount;
sbuf = ((char *)redbuf) + (offset*ext);
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf-(unsigned long)handle->tmpbuf, true, recvcount, datatype, r, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
res = NBC_Sched_copy(redbuf-(unsigned long)handle->tmpbuf, true, recvcount, datatype, recvbuf, false, recvcount, datatype, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
/* tmpbuf is freed with the handle */
return NBC_OK;
}
int ompi_coll_libnbc_ireduce_scatter_block_inter(void *sbuf, void *rbuf, int rcount, struct ompi_datatype_t *dtype,
struct ompi_op_t *op, struct ompi_communicator_t *comm,
ompi_request_t **request, struct mca_coll_base_module_2_1_0_t *module) {
int peer, rank, res, count, rsize;
MPI_Aint ext;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = MPI_Type_extent(dtype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return NBC_OOR; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
count = rcount * rsize;
handle->tmpbuf = malloc(2*ext*count);
if(handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
/* send my data to the remote root */
res = NBC_Sched_send(sbuf, false, count, dtype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (0 == rank) {
res = NBC_Sched_recv((void *) 0, true, count, dtype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
for (peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv((void *)(ext * count), true, count, dtype, peer, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_op((void *) 0, true, (void *)(ext * count), true, (void *) 0, true, count, dtype, op, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
/* exchange data with remote root for scatter phase (we *could* use the local communicator to do the scatter) */
res = NBC_Sched_recv((void *)(ext * count), true, count, dtype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_send((void *) 0, true, count, dtype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
/* scatter */
for (peer = 0 ; peer < rsize ; ++peer) {
res = NBC_Sched_send((void *)(ext * (count + peer * rcount)), true, rcount, dtype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* receive my block */
res = NBC_Sched_recv(rbuf, true, rcount, dtype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
/* tmpbuf is freed with the handle */
return NBC_OK;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -7,6 +8,8 @@
* reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -33,275 +36,255 @@ void NBC_Print_times(double div) {
}
#endif
/* allocates a new schedule array */
int NBC_Sched_create(NBC_Schedule* schedule) {
int *ptr;
static void nbc_schedule_constructor (NBC_Schedule *schedule) {
/* initial total size of the schedule */
schedule->size = sizeof (int);
schedule->current_round_offset = 0;
schedule->data = calloc (1, schedule->size);
}
*schedule=malloc(2*sizeof(int));
if(*schedule == NULL) { return NBC_OOR; }
static void nbc_schedule_destructor (NBC_Schedule *schedule) {
free (schedule->data);
schedule->data = NULL;
}
/* initialize the schedule */
ptr = (int*) *schedule;
ptr[0] = 2 * sizeof(int); /* initial total size of the schedule */
ptr[1] = 0; /* initial round-schedule has num=(int)0 and no actions */
/* The schedule's final end=(char)0 delimiter won't be added until NBC_Sched_commit(). */
OBJ_CLASS_INSTANCE(NBC_Schedule, opal_object_t, nbc_schedule_constructor,
nbc_schedule_destructor);
return NBC_OK;
static int nbc_schedule_grow (NBC_Schedule *schedule, int additional) {
void *tmp;
int size;
/* get current size of schedule */
size = nbc_schedule_get_size (schedule);
tmp = realloc (schedule->data, size + additional);
if (NULL == tmp) {
NBC_Error ("Could not increase the size of NBC schedule");
return OMPI_ERR_OUT_OF_RESOURCE;
}
schedule->data = tmp;
return OMPI_SUCCESS;
}
static int nbc_schedule_round_append (NBC_Schedule *schedule, void *data, int data_size, bool barrier) {
int ret, size = nbc_schedule_get_size (schedule);
if (barrier) {
ret = nbc_schedule_grow (schedule, data_size + 1 + sizeof (int));
} else {
ret = nbc_schedule_grow (schedule, data_size);
}
if (OMPI_SUCCESS != ret) {
return ret;
}
/* append to the round-schedule */
if (data_size) {
memcpy (schedule->data + size, data, data_size);
/* increase number of elements in round-schedule */
nbc_schedule_inc_round (schedule);
/* increase size of schedule */
nbc_schedule_inc_size (schedule, data_size);
}
if (barrier) {
/* add the barrier */
schedule->data[size + data_size] = 1;
/* set next round counter to 0 */
memset (schedule->data + size + data_size + 1, 0, sizeof (int));
NBC_DEBUG(10, "ended round at byte %i\n", size + data_size + 1);
schedule->current_round_offset = size + data_size + 1;
/* increase size of schedule */
nbc_schedule_inc_size (schedule, sizeof (int) + 1);
}
return OMPI_SUCCESS;
}
/* this function puts a send into the schedule */
int NBC_Sched_send(void* buf, char tmpbuf, int count, MPI_Datatype datatype, int dest, NBC_Schedule *schedule) {
int size;
char* ptr;
NBC_Fn_type type = SEND;
int NBC_Sched_send (void* buf, char tmpbuf, int count, MPI_Datatype datatype, int dest, NBC_Schedule *schedule, bool barrier) {
NBC_Args_send send_args;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule is %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_send));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
int ret;
/* store the passed arguments */
send_args.buf=buf;
send_args.tmpbuf=tmpbuf;
send_args.count=count;
send_args.datatype=datatype;
send_args.dest=dest;
send_args.type = SEND;
send_args.buf = buf;
send_args.tmpbuf = tmpbuf;
send_args.count = count;
send_args.datatype = datatype;
send_args.dest = dest;
/* append to the round-schedule */
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,type);
NBC_PUT_BYTES(ptr,send_args);
ret = nbc_schedule_round_append (schedule, &send_args, sizeof (send_args), barrier);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* increase number of elements in round-schedule */
NBC_INC_NUM_ROUND(*schedule);
NBC_DEBUG(10, "adding send - ends at byte %i\n", (int)(size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_send)));
NBC_DEBUG(10, "added send - ends at byte %i\n", nbc_schedule_get_size (schedule));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(NBC_Fn_type)+sizeof(NBC_Args_send));
return NBC_OK;
return OMPI_SUCCESS;
}
/* this function puts a receive into the schedule */
int NBC_Sched_recv(void* buf, char tmpbuf, int count, MPI_Datatype datatype, int source, NBC_Schedule *schedule) {
int size;
char* ptr;
NBC_Fn_type type = RECV;
int NBC_Sched_recv (void* buf, char tmpbuf, int count, MPI_Datatype datatype, int source, NBC_Schedule *schedule, bool barrier) {
NBC_Args_recv recv_args;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule is %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_recv));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
int ret;
/* store the passed arguments */
recv_args.buf=buf;
recv_args.tmpbuf=tmpbuf;
recv_args.count=count;
recv_args.datatype=datatype;
recv_args.source=source;
recv_args.type = RECV;
recv_args.buf = buf;
recv_args.tmpbuf = tmpbuf;
recv_args.count = count;
recv_args.datatype = datatype;
recv_args.source = source;
/* append to the round-schedule */
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,type);
NBC_PUT_BYTES(ptr,recv_args);
ret = nbc_schedule_round_append (schedule, &recv_args, sizeof (recv_args), barrier);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* increase number of elements in round-schedule */
NBC_INC_NUM_ROUND(*schedule);
NBC_DEBUG(10, "adding receive - ends at byte %i\n", (int)(size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_recv)));
NBC_DEBUG(10, "added receive - ends at byte %d\n", nbc_schedule_get_size (schedule));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(NBC_Fn_type)+sizeof(NBC_Args_recv));
return NBC_OK;
return OMPI_SUCCESS;
}
/* this function puts an operation into the schedule */
int NBC_Sched_op(void *buf3, char tmpbuf3, void* buf1, char tmpbuf1, void* buf2, char tmpbuf2, int count, MPI_Datatype datatype, MPI_Op op, NBC_Schedule *schedule) {
int size;
char* ptr;
NBC_Fn_type type = OP;
int NBC_Sched_op (void *buf3, char tmpbuf3, void* buf1, char tmpbuf1, void* buf2, char tmpbuf2, int count, MPI_Datatype datatype,
MPI_Op op, NBC_Schedule *schedule, bool barrier) {
NBC_Args_op op_args;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule is %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_op));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
int ret;
/* store the passed arguments */
op_args.buf1=buf1;
op_args.buf2=buf2;
op_args.buf3=buf3;
op_args.tmpbuf1=tmpbuf1;
op_args.tmpbuf2=tmpbuf2;
op_args.tmpbuf3=tmpbuf3;
op_args.count=count;
op_args.op=op;
op_args.datatype=datatype;
op_args.type = OP;
op_args.buf1 = buf1;
op_args.buf2 = buf2;
op_args.buf3 = buf3;
op_args.tmpbuf1 = tmpbuf1;
op_args.tmpbuf2 = tmpbuf2;
op_args.tmpbuf3 = tmpbuf3;
op_args.count = count;
op_args.op = op;
op_args.datatype = datatype;
/* append to the round-schedule */
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,type);
NBC_PUT_BYTES(ptr,op_args);
ret = nbc_schedule_round_append (schedule, &op_args, sizeof (op_args), barrier);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* increase number of elements in round-schedule */
NBC_INC_NUM_ROUND(*schedule);
NBC_DEBUG(10, "adding op - ends at byte %i\n", (int)(size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_op)));
NBC_DEBUG(10, "added op - ends at byte %i\n", nbc_schedule_get_size (schedule));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(NBC_Fn_type)+sizeof(NBC_Args_op));
return NBC_OK;
return OMPI_SUCCESS;
}
/* this function puts a copy into the schedule */
int NBC_Sched_copy(void *src, char tmpsrc, int srccount, MPI_Datatype srctype, void *tgt, char tmptgt, int tgtcount, MPI_Datatype tgttype, NBC_Schedule *schedule) {
int size;
char* ptr;
NBC_Fn_type type = COPY;
int NBC_Sched_copy (void *src, char tmpsrc, int srccount, MPI_Datatype srctype, void *tgt, char tmptgt, int tgtcount,
MPI_Datatype tgttype, NBC_Schedule *schedule, bool barrier) {
NBC_Args_copy copy_args;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule is %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_copy));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
int ret;
/* store the passed arguments */
copy_args.src=src;
copy_args.tmpsrc=tmpsrc;
copy_args.srccount=srccount;
copy_args.srctype=srctype;
copy_args.tgt=tgt;
copy_args.tmptgt=tmptgt;
copy_args.tgtcount=tgtcount;
copy_args.tgttype=tgttype;
copy_args.type = COPY;
copy_args.src = src;
copy_args.tmpsrc = tmpsrc;
copy_args.srccount = srccount;
copy_args.srctype = srctype;
copy_args.tgt = tgt;
copy_args.tmptgt = tmptgt;
copy_args.tgtcount = tgtcount;
copy_args.tgttype = tgttype;
/* append to the round-schedule */
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,type);
NBC_PUT_BYTES(ptr,copy_args);
ret = nbc_schedule_round_append (schedule, &copy_args, sizeof (copy_args), barrier);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* increase number of elements in round-schedule */
NBC_INC_NUM_ROUND(*schedule);
NBC_DEBUG(10, "adding copy - ends at byte %i\n", (int)(size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_copy)));
NBC_DEBUG(10, "added copy - ends at byte %i\n", nbc_schedule_get_size (schedule));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(NBC_Fn_type)+sizeof(NBC_Args_copy));
return NBC_OK;
return OMPI_SUCCESS;
}
/* this function puts a unpack into the schedule */
int NBC_Sched_unpack(void *inbuf, char tmpinbuf, int count, MPI_Datatype datatype, void *outbuf, char tmpoutbuf, NBC_Schedule *schedule) {
int size;
char* ptr;
NBC_Fn_type type = UNPACK;
int NBC_Sched_unpack (void *inbuf, char tmpinbuf, int count, MPI_Datatype datatype, void *outbuf, char tmpoutbuf,
NBC_Schedule *schedule, bool barrier) {
NBC_Args_unpack unpack_args;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule is %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_unpack));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
int ret;
/* store the passed arguments */
unpack_args.inbuf=inbuf;
unpack_args.tmpinbuf=tmpinbuf;
unpack_args.count=count;
unpack_args.datatype=datatype;
unpack_args.outbuf=outbuf;
unpack_args.tmpoutbuf=tmpoutbuf;
unpack_args.type = UNPACK;
unpack_args.inbuf = inbuf;
unpack_args.tmpinbuf = tmpinbuf;
unpack_args.count = count;
unpack_args.datatype = datatype;
unpack_args.outbuf = outbuf;
unpack_args.tmpoutbuf = tmpoutbuf;
/* append to the round-schedule */
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,type);
NBC_PUT_BYTES(ptr,unpack_args);
ret = nbc_schedule_round_append (schedule, &unpack_args, sizeof (unpack_args), barrier);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* increase number of elements in round-schedule */
NBC_INC_NUM_ROUND(*schedule);
NBC_DEBUG(10, "adding unpack - ends at byte %i\n", (int)(size+sizeof(NBC_Fn_type)+sizeof(NBC_Args_unpack)));
NBC_DEBUG(10, "added unpack - ends at byte %i\n", nbc_schedule_get_size (schedule));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(NBC_Fn_type)+sizeof(NBC_Args_unpack));
return NBC_OK;
return OMPI_SUCCESS;
}
/* this function ends a round of a schedule */
int NBC_Sched_barrier(NBC_Schedule *schedule) {
int size, num = 0;
char *ptr;
char delimiter = 1;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("round terminated at %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(char)+sizeof(int));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
ptr = (char*)*schedule + size;
NBC_PUT_BYTES(ptr,delimiter); /* round-schedule delimiter */
NBC_PUT_BYTES(ptr,num); /* initialize num=0 for next round-schedule */
NBC_DEBUG(10, "ending round at byte %i\n", (int)(size+sizeof(char)+sizeof(int)));
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(char)+sizeof(int));
return NBC_OK;
int NBC_Sched_barrier (NBC_Schedule *schedule) {
return nbc_schedule_round_append (schedule, NULL, 0, true);
}
/* this function ends a schedule */
int NBC_Sched_commit(NBC_Schedule *schedule) {
int size;
int size = nbc_schedule_get_size (schedule);
char *ptr;
int ret;
/* get size of actual schedule */
NBC_GET_SIZE(*schedule, size);
/*printf("schedule terminated at %i bytes\n", size);*/
*schedule = (NBC_Schedule)realloc(*schedule, size+sizeof(char));
if(*schedule == NULL) { printf("Error in realloc()\n"); return NBC_OOR; }
ret = nbc_schedule_grow (schedule, 1);
if (OMPI_SUCCESS != ret) {
return ret;
}
/* add the barrier char (0) because this is the last round */
*(char*)((char*)*schedule+size)=0;
NBC_DEBUG(10, "closing schedule %p at byte %i\n", *schedule, (int)(size+sizeof(char)));
ptr = schedule->data + size;
*((char *) ptr) = 0;
/* increase size of schedule */
NBC_INC_SIZE(*schedule, sizeof(char));
nbc_schedule_inc_size (schedule, 1);
return NBC_OK;
NBC_DEBUG(10, "closed schedule %p at byte %i\n", schedule, (int)(size + 1));
return OMPI_SUCCESS;
}
/* finishes a request
*
* to be called *only* from the progress thread !!! */
static inline int NBC_Free(NBC_Handle* handle) {
static inline void NBC_Free (NBC_Handle* handle) {
#ifdef NBC_CACHE_SCHEDULE
/* do not free schedule because it is in the cache */
handle->schedule = NULL;
#else
if(handle->schedule != NULL) {
/* free schedule */
free((void*)*(handle->schedule));
free((void*)handle->schedule);
if (NULL != handle->schedule) {
/* release schedule */
OBJ_RELEASE (handle->schedule);
handle->schedule = NULL;
}
#endif
/* if the nbc_I<collective> attached some data */
/* problems with schedule cache here, see comment (TODO) in
* nbc_internal.h */
if(NULL != handle->tmpbuf) {
if (NULL != handle->tmpbuf) {
free((void*)handle->tmpbuf);
handle->tmpbuf = NULL;
}
return NBC_OK;
}
/* progresses a request
@ -309,98 +292,103 @@ static inline int NBC_Free(NBC_Handle* handle) {
* to be called *only* from the progress thread !!! */
int NBC_Progress(NBC_Handle *handle) {
int flag, res, ret=NBC_CONTINUE;
long size;
unsigned long size;
char *delim;
/* the handle is done if there is no schedule attached */
if(handle->schedule != NULL) {
if((handle->req_count > 0) && (handle->req_array != NULL)) {
NBC_DEBUG(50, "NBC_Progress: testing for %i requests\n", handle->req_count);
#ifdef NBC_TIMING
Test_time -= MPI_Wtime();
#endif
res = ompi_request_test_all(handle->req_count, handle->req_array, &flag, MPI_STATUSES_IGNORE);
if(res != OMPI_SUCCESS) { printf("MPI Error in MPI_Testall() (%i)\n", res); ret=res; goto error; }
#ifdef NBC_TIMING
Test_time += MPI_Wtime();
#endif
} else {
flag = 1; /* we had no open requests -> proceed to next round */
}
/* a round is finished */
if(flag) {
/* adjust delim to start of current round */
NBC_DEBUG(5, "NBC_Progress: going in schedule %p to row-offset: %li\n", *handle->schedule, handle->row_offset);
delim = (char*)*handle->schedule + handle->row_offset;
NBC_DEBUG(10, "delim: %p\n", delim);
NBC_GET_ROUND_SIZE(delim, size);
NBC_DEBUG(10, "size: %li\n", size);
/* adjust delim to end of current round -> delimiter */
delim = delim + size;
if(handle->req_array != NULL) {
/* free request array */
free((void*)handle->req_array);
handle->req_array = NULL;
}
handle->req_count = 0;
if(*delim == 0) {
/* this was the last round - we're done */
NBC_DEBUG(5, "NBC_Progress last round finished - we're done\n");
res = NBC_Free(handle);
if((NBC_OK != res)) { printf("Error in NBC_Free() (%i)\n", res); ret=res; goto error; }
return NBC_OK;
} else {
NBC_DEBUG(5, "NBC_Progress round finished - goto next round\n");
/* move delim to start of next round */
delim = delim+1;
/* initializing handle for new virgin round */
handle->row_offset = (long)delim - (long)*handle->schedule;
/* kick it off */
res = NBC_Start_round(handle);
if(NBC_OK != res) { printf("Error in NBC_Start_round() (%i)\n", res); ret=res; goto error; }
}
}
} else {
ret= NBC_OK;
if (NULL == handle->schedule) {
return NBC_OK;
}
if ((handle->req_count > 0) && (handle->req_array != NULL)) {
NBC_DEBUG(50, "NBC_Progress: testing for %i requests\n", handle->req_count);
#ifdef NBC_TIMING
Test_time -= MPI_Wtime();
#endif
res = ompi_request_test_all(handle->req_count, handle->req_array, &flag, MPI_STATUSES_IGNORE);
if(res != OMPI_SUCCESS) {
NBC_Error ("MPI Error in MPI_Testall() (%i)", res);
return res;
}
#ifdef NBC_TIMING
Test_time += MPI_Wtime();
#endif
} else {
flag = 1; /* we had no open requests -> proceed to next round */
}
/* a round is finished */
if (flag) {
/* adjust delim to start of current round */
NBC_DEBUG(5, "NBC_Progress: going in schedule %p to row-offset: %li\n", handle->schedule, handle->row_offset);
delim = handle->schedule->data + handle->row_offset;
NBC_DEBUG(10, "delim: %p\n", delim);
nbc_get_round_size(delim, &size);
NBC_DEBUG(10, "size: %li\n", size);
/* adjust delim to end of current round -> delimiter */
delim = delim + size;
if (NULL != handle->req_array) {
/* free request array */
free (handle->req_array);
handle->req_array = NULL;
}
handle->req_count = 0;
if (*delim == 0) {
/* this was the last round - we're done */
NBC_DEBUG(5, "NBC_Progress last round finished - we're done\n");
NBC_Free(handle);
return NBC_OK;
}
NBC_DEBUG(5, "NBC_Progress round finished - goto next round\n");
/* move delim to start of next round */
/* initializing handle for new virgin round */
handle->row_offset = (intptr_t) (delim + 1) - (intptr_t) handle->schedule->data;
/* kick it off */
res = NBC_Start_round(handle);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Error ("Error in NBC_Start_round() (%i)", res);
return res;
}
}
error:
return ret;
}
static inline int NBC_Start_round(NBC_Handle *handle) {
int num; /* number of operations */
int i, res, ret=NBC_OK;
int res;
char* ptr;
MPI_Request *tmp;
NBC_Fn_type type;
NBC_Args_send sendargs;
NBC_Args_recv recvargs;
NBC_Args_op opargs;
NBC_Args_copy copyargs;
NBC_Args_unpack unpackargs;
NBC_Schedule myschedule;
void *buf1, *buf2, *buf3;
/* get round-schedule address */
myschedule = (NBC_Schedule*)((char*)*handle->schedule + handle->row_offset);
ptr = (char*) myschedule;
ptr = handle->schedule->data + handle->row_offset;
NBC_GET_BYTES(ptr,num);
NBC_DEBUG(10, "start_round round at address %p : posting %i operations\n", myschedule, num);
NBC_DEBUG(10, "start_round round at offset %d : posting %i operations\n", handle->row_offset, num);
for (i=0; i<num; i++) {
NBC_GET_BYTES(ptr,type);
for (int i = 0 ; i < num ; ++i) {
int offset = (intptr_t)(ptr - handle->schedule->data);
memcpy (&type, ptr, sizeof (type));
switch(type) {
case SEND:
NBC_DEBUG(5," SEND (offset %li) ", (long)ptr-(long)myschedule);
NBC_DEBUG(5," SEND (offset %li) ", offset);
NBC_GET_BYTES(ptr,sendargs);
NBC_DEBUG(5,"*buf: %p, count: %i, type: %lu, dest: %i, tag: %i)\n", sendargs.buf, sendargs.count, (unsigned long)sendargs.datatype, sendargs.dest, handle->tag);
NBC_DEBUG(5,"*buf: %p, count: %i, type: %p, dest: %i, tag: %i)\n", sendargs.buf,
sendargs.count, sendargs.datatype, sendargs.dest, handle->tag);
/* get an additional request */
handle->req_count++;
/* get buffer */
@ -412,18 +400,30 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
#ifdef NBC_TIMING
Isend_time -= MPI_Wtime();
#endif
handle->req_array = (MPI_Request*)realloc((void*)handle->req_array, (handle->req_count)*sizeof(MPI_Request));
NBC_CHECK_NULL(handle->req_array);
res = MCA_PML_CALL(isend(buf1, sendargs.count, sendargs.datatype, sendargs.dest, handle->tag, MCA_PML_BASE_SEND_STANDARD, handle->comm, handle->req_array+handle->req_count-1));
if(OMPI_SUCCESS != res) { printf("Error in MPI_Isend(%lu, %i, %lu, %i, %i, %lu) (%i)\n", (unsigned long)buf1, sendargs.count, (unsigned long)sendargs.datatype, sendargs.dest, handle->tag, (unsigned long)handle->comm, res); ret=res; goto error; }
tmp = (MPI_Request *) realloc ((void *) handle->req_array, handle->req_count * sizeof (MPI_Request));
if (NULL == tmp) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
handle->req_array = tmp;
res = MCA_PML_CALL(isend(buf1, sendargs.count, sendargs.datatype, sendargs.dest, handle->tag,
MCA_PML_BASE_SEND_STANDARD, handle->comm,
handle->req_array+handle->req_count - 1));
if (OMPI_SUCCESS != res) {
NBC_Error ("Error in MPI_Isend(%lu, %i, %p, %i, %i, %lu) (%i)", (unsigned long)buf1, sendargs.count,
sendargs.datatype, sendargs.dest, handle->tag, (unsigned long)handle->comm, res);
return res;
}
#ifdef NBC_TIMING
Isend_time += MPI_Wtime();
#endif
break;
case RECV:
NBC_DEBUG(5, " RECV (offset %li) ", (long)ptr-(long)myschedule);
NBC_DEBUG(5, " RECV (offset %li) ", offset);
NBC_GET_BYTES(ptr,recvargs);
NBC_DEBUG(5, "*buf: %p, count: %i, type: %lu, source: %i, tag: %i)\n", recvargs.buf, recvargs.count, (unsigned long)recvargs.datatype, recvargs.source, handle->tag);
NBC_DEBUG(5, "*buf: %p, count: %i, type: %p, source: %i, tag: %i)\n", recvargs.buf, recvargs.count,
recvargs.datatype, recvargs.source, handle->tag);
/* get an additional request - TODO: req_count NOT thread safe */
handle->req_count++;
/* get buffer */
@ -435,18 +435,29 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
#ifdef NBC_TIMING
Irecv_time -= MPI_Wtime();
#endif
handle->req_array = (MPI_Request*)realloc((void*)handle->req_array, (handle->req_count)*sizeof(MPI_Request));
NBC_CHECK_NULL(handle->req_array);
res = MCA_PML_CALL(irecv(buf1, recvargs.count, recvargs.datatype, recvargs.source, handle->tag, handle->comm, handle->req_array+handle->req_count-1));
if(OMPI_SUCCESS != res) { printf("Error in MPI_Irecv(%lu, %i, %lu, %i, %i, %lu) (%i)\n", (unsigned long)buf1, recvargs.count, (unsigned long)recvargs.datatype, recvargs.source, handle->tag, (unsigned long)handle->comm, res); ret=res; goto error; }
tmp = (MPI_Request *) realloc ((void *) handle->req_array, handle->req_count * sizeof (MPI_Request));
if (NULL == tmp) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
handle->req_array = tmp;
res = MCA_PML_CALL(irecv(buf1, recvargs.count, recvargs.datatype, recvargs.source, handle->tag, handle->comm,
handle->req_array+handle->req_count-1));
if (OMPI_SUCCESS != res) {
NBC_Error("Error in MPI_Irecv(%lu, %i, %p, %i, %i, %lu) (%i)", (unsigned long)buf1, recvargs.count,
recvargs.datatype, recvargs.source, handle->tag, (unsigned long)handle->comm, res);
return res;
}
#ifdef NBC_TIMING
Irecv_time += MPI_Wtime();
#endif
break;
case OP:
NBC_DEBUG(5, " OP (offset %li) ", (long)ptr-(long)myschedule);
NBC_DEBUG(5, " OP (offset %li) ", offset);
NBC_GET_BYTES(ptr,opargs);
NBC_DEBUG(5, "*buf1: %p, buf2: %p, buf3: %p, count: %i, type: %lu)\n", opargs.buf1, opargs.buf2, opargs.buf3, opargs.count, (unsigned long)opargs.datatype);
NBC_DEBUG(5, "*buf1: %p, buf2: %p, buf3: %p, count: %i, type: %p)\n", opargs.buf1, opargs.buf2,
opargs.buf3, opargs.count, opargs.datatype);
/* get buffers */
if(opargs.tmpbuf1) {
buf1=(char*)handle->tmpbuf+(long)opargs.buf1;
@ -466,9 +477,11 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
ompi_3buff_op_reduce(opargs.op, buf1, buf2, buf3, opargs.count, opargs.datatype);
break;
case COPY:
NBC_DEBUG(5, " COPY (offset %li) ", (long)ptr-(long)myschedule);
NBC_DEBUG(5, " COPY (offset %li) ", offset);
NBC_GET_BYTES(ptr,copyargs);
NBC_DEBUG(5, "*src: %lu, srccount: %i, srctype: %lu, *tgt: %lu, tgtcount: %i, tgttype: %lu)\n", (unsigned long)copyargs.src, copyargs.srccount, (unsigned long)copyargs.srctype, (unsigned long)copyargs.tgt, copyargs.tgtcount, (unsigned long)copyargs.tgttype);
NBC_DEBUG(5, "*src: %lu, srccount: %i, srctype: %p, *tgt: %lu, tgtcount: %i, tgttype: %p)\n",
(unsigned long) copyargs.src, copyargs.srccount, copyargs.srctype,
(unsigned long) copyargs.tgt, copyargs.tgtcount, copyargs.tgttype);
/* get buffers */
if(copyargs.tmpsrc) {
buf1=(char*)handle->tmpbuf+(long)copyargs.src;
@ -480,13 +493,17 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
} else {
buf2=copyargs.tgt;
}
res = NBC_Copy(buf1, copyargs.srccount, copyargs.srctype, buf2, copyargs.tgtcount, copyargs.tgttype, handle->comm);
if(res != NBC_OK) { printf("NBC_Copy() failed (code: %i)\n", res); ret=res; goto error; }
res = NBC_Copy (buf1, copyargs.srccount, copyargs.srctype, buf2, copyargs.tgtcount, copyargs.tgttype,
handle->comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
break;
case UNPACK:
NBC_DEBUG(5, " UNPACK (offset %li) ", (long)ptr-(long)myschedule);
NBC_DEBUG(5, " UNPACK (offset %li) ", offset);
NBC_GET_BYTES(ptr,unpackargs);
NBC_DEBUG(5, "*src: %lu, srccount: %i, srctype: %lu, *tgt: %lu\n", (unsigned long)unpackargs.inbuf, unpackargs.count, (unsigned long)unpackargs.datatype, (unsigned long)unpackargs.outbuf);
NBC_DEBUG(5, "*src: %lu, srccount: %i, srctype: %p, *tgt: %lu\n", (unsigned long) unpackargs.inbuf,
unpackargs.count, unpackargs.datatype, (unsigned long) unpackargs.outbuf);
/* get buffers */
if(unpackargs.tmpinbuf) {
buf1=(char*)handle->tmpbuf+(long)unpackargs.inbuf;
@ -498,13 +515,16 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
} else {
buf2=unpackargs.outbuf;
}
res = NBC_Unpack(buf1, unpackargs.count, unpackargs.datatype, buf2, handle->comm);
if(res != NBC_OK) { printf("NBC_Unpack() failed (code: %i)\n", res); ret=res; goto error; }
res = NBC_Unpack (buf1, unpackargs.count, unpackargs.datatype, buf2, handle->comm);
if (OMPI_SUCCESS != res) {
NBC_Error ("NBC_Unpack() failed (code: %i)", res);
return res;
}
break;
default:
printf("NBC_Start_round: bad type %li at offset %li\n", (long)type, (long)ptr-(long)myschedule);
ret=NBC_BAD_SCHED;
goto error;
NBC_Error ("NBC_Start_round: bad type %li at offset %li", (long)type, offset);
return OMPI_ERROR;
}
}
@ -513,13 +533,14 @@ static inline int NBC_Start_round(NBC_Handle *handle) {
*
* threaded case: calling progress in the first round can lead to a
* deadlock if NBC_Free is called in this round :-( */
if(handle->row_offset != sizeof(int)) {
if (handle->row_offset) {
res = NBC_Progress(handle);
if((NBC_OK != res) && (NBC_CONTINUE != res)) { printf("Error in NBC_Progress() (%i)\n", res); ret=res; goto error; }
if ((NBC_OK != res) && (NBC_CONTINUE != res)) {
return OMPI_ERROR;
}
}
error:
return ret;
return OMPI_SUCCESS;
}
int NBC_Init_handle(struct ompi_communicator_t *comm, ompi_coll_libnbc_request_t **request, ompi_coll_libnbc_module_t *comminfo)
@ -537,8 +558,7 @@ int NBC_Init_handle(struct ompi_communicator_t *comm, ompi_coll_libnbc_request_t
handle->req_array = NULL;
handle->comm = comm;
handle->schedule = NULL;
/* first int is the schedule size */
handle->row_offset = sizeof(int);
handle->row_offset = 0;
/******************** Do the tag and shadow comm administration ... ***************/
@ -555,7 +575,7 @@ int NBC_Init_handle(struct ompi_communicator_t *comm, ompi_coll_libnbc_request_t
}
OPAL_THREAD_UNLOCK(&comminfo->mutex);
handle->tag=comminfo->tag;
handle->tag = tmp_tag;
/* register progress */
if (need_register) {
@ -574,7 +594,12 @@ int NBC_Init_handle(struct ompi_communicator_t *comm, ompi_coll_libnbc_request_t
NBC_DEBUG(3, "got tag %i\n", handle->tag);
return NBC_OK;
return OMPI_SUCCESS;
}
void NBC_Return_handle(ompi_coll_libnbc_request_t *request) {
NBC_Free (request);
OMPI_COLL_LIBNBC_REQUEST_RETURN(request);
}
int NBC_Init_comm(MPI_Comm comm, NBC_Comminfo *comminfo) {
@ -636,11 +661,12 @@ int NBC_Start(NBC_Handle *handle, NBC_Schedule *schedule) {
/* kick off first round */
res = NBC_Start_round(handle);
if((NBC_OK != res)) { printf("Error in NBC_Start_round() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
opal_list_append(&mca_coll_libnbc_component.active_requests, &(handle->super.super.super));
return NBC_OK;
return OMPI_SUCCESS;
}
#ifdef NBC_CACHE_SCHEDULE
@ -650,13 +676,8 @@ void NBC_SchedCache_args_delete_key_dummy(void *k) {
}
void NBC_SchedCache_args_delete(void *entry) {
struct NBC_dummyarg *tmp;
tmp = (struct NBC_dummyarg*)entry;
/* free taglistentry */
free((void*)*(tmp->schedule));
/* the schedule pointer itself is also malloc'd */
free((void*)tmp->schedule);
free((void*)tmp);
struct NBC_dummyarg *tmp = (struct NBC_dummyarg*)entry;
OBJ_RELEASE(tmp->schedule);
free(entry);
}
#endif

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -15,19 +18,20 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Allgather_args_compare(NBC_Allgather_args *a, NBC_Allgather_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->sendcount == b->sendcount) &&
(a->sendtype == b->sendtype) &&
(a->recvbuf == b->recvbuf) &&
(a->recvcount == b->recvcount) &&
(a->recvtype == b->recvtype) ) {
return 0;
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if( a->sendbuf < b->sendbuf ) {
return -1;
}
return +1;
}
return 1;
}
#endif
@ -39,7 +43,7 @@ int ompi_coll_libnbc_iallgather(void* sendbuf, int sendcount, MPI_Datatype sendt
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, p, res, r;
int rank, p, res;
MPI_Aint rcvext;
NBC_Schedule *schedule;
char *rbuf, *sbuf, inplace;
@ -47,146 +51,181 @@ int ompi_coll_libnbc_iallgather(void* sendbuf, int sendcount, MPI_Datatype sendt
NBC_Allgather_args *args, *found, search;
#endif
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
handle->tmpbuf = NULL;
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) {
return res;
}
if (inplace) {
sendtype = recvtype;
sendcount = recvcount;
sendtype = recvtype;
sendcount = recvcount;
} else {
/* copy my data to receive buffer */
rbuf = ((char *)recvbuf) + (rank*recvcount*rcvext);
res = NBC_Copy(sendbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
rbuf = (char *) recvbuf + rank * recvcount * rcvext;
res = NBC_Copy (sendbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.sendcount=sendcount;
search.sendtype=sendtype;
search.recvbuf=recvbuf;
search.recvcount=recvcount;
search.recvtype=recvtype;
found = (NBC_Allgather_args *)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLGATHER], &search);
if(found == NULL) {
search.sendbuf = sendbuf;
search.sendcount = sendcount;
search.sendtype = sendtype;
search.recvbuf = recvbuf;
search.recvcount = recvcount;
search.recvtype = recvtype;
found = (NBC_Allgather_args *) hb_tree_search ((hb_tree*)libnbc_module->NBC_Dict[NBC_ALLGATHER], &search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(NBC_OK != res) { printf("Error in NBC_Sched_create, (%i)\n", res); return res; }
sbuf = ((char *)recvbuf) + (rank*recvcount*rcvext);
sbuf = (char *)recvbuf + rank * recvcount * rcvext;
/* do p-1 rounds */
for(r=0;r<p;r++) {
for(int r = 0 ; r < p ; ++r) {
if(r != rank) {
/* recv from rank r */
rbuf = ((char *)recvbuf) + r*(recvcount*rcvext);
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
rbuf = (char *)recvbuf + r * recvcount * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
/* send to rank r - not from the sendbuf to optimize MPI_IN_PLACE */
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Allgather_args*)malloc(sizeof(NBC_Allgather_args));
args->sendbuf=sendbuf;
args->sendcount=sendcount;
args->sendtype=sendtype;
args->recvbuf=recvbuf;
args->recvcount=recvcount;
args->recvtype=recvtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLGATHER], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
args = (NBC_Allgather_args *) malloc (sizeof (args));
args->sendbuf = sendbuf;
args->sendcount = sendcount;
args->sendtype = sendtype;
args->recvbuf = recvbuf;
args->recvcount = recvcount;
args->recvtype = recvtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLGATHER], args, args, 0);
if (res != 0) {
free (args);
} else {
OBJ_RETAIN(schedule);
}
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_ALLGATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLGATHER], &handle->comminfo->NBC_Dict_size[NBC_ALLGATHER]);
if (++libnbc_module->NBC_Dict_size[NBC_ALLGATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLGATHER], &libnbc_module->NBC_Dict_size[NBC_ALLGATHER]);
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OMPI_COLL_LIBNBC_REQUEST_RETURN(handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_iallgather_inter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, r, rsize;
int res, rsize;
MPI_Aint rcvext;
NBC_Schedule *schedule;
char *rbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
res = NBC_Sched_create(schedule);
if(NBC_OK != res) { printf("Error in NBC_Sched_create, (%i)\n", res); return res; }
/* do rsize - 1 rounds */
for(r = 0 ; r < rsize ; ++r) {
/* recv from rank r */
rbuf = ((char *)recvbuf) + r*(recvcount*rcvext);
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
/* send to rank r */
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
/*NBC_PRINT_SCHED(*schedule);*/
/* set up schedule */
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
/* do rsize - 1 rounds */
for (int r = 0 ; r < rsize ; ++r) {
/* recv from rank r */
rbuf = (char *) recvbuf + r * recvcount * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
/* send to rank r */
res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OMPI_COLL_LIBNBC_REQUEST_RETURN(handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -8,7 +9,7 @@
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
* Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -32,117 +33,150 @@ int ompi_coll_libnbc_iallgatherv(void* sendbuf, int sendcount, MPI_Datatype send
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, p, res, r, speer, rpeer;
int rank, p, res, speer, rpeer;
MPI_Aint rcvext;
NBC_Schedule *schedule;
char *rbuf, *sbuf, inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, (%i)\n", res); return res; }
res = MPI_Type_extent (recvtype, &rcvext);
if (OPAL_UNLIKELY(MPI_SUCCESS != res)) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
if (inplace) {
sendtype = recvtype;
sendcount = recvcounts[rank];
} else {
/* copy my data to receive buffer */
rbuf = ((char *)recvbuf) + (displs[rank]*rcvext);
res = NBC_Copy(sendbuf, sendcount, sendtype, rbuf, recvcounts[rank], recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
rbuf = (char *) recvbuf + displs[rank] * rcvext;
res = NBC_Copy (sendbuf, sendcount, sendtype, rbuf, recvcounts[rank], recvtype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
sbuf = ((char*) recvbuf) + (displs[rank]*rcvext);
schedule = OBJ_NEW(NBC_Schedule);
if (NULL == schedule) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
sbuf = (char *) recvbuf + displs[rank] * rcvext;
/* do p-1 rounds */
for(r=1;r<p;r++) {
speer = (rank+r)%p;
rpeer = (rank-r+p)%p;
rbuf = ((char *)recvbuf) + (displs[rpeer]*rcvext);
for (int r = 1 ; r < p ; ++r) {
speer = (rank + r) % p;
rpeer = (rank - r + p) % p;
rbuf = (char *)recvbuf + displs[rpeer] * rcvext;
res = NBC_Sched_recv(rbuf, false, recvcounts[rpeer], recvtype, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, speer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_recv (rbuf, false, recvcounts[rpeer], recvtype, rpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, speer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_iallgatherv_inter(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int *recvcounts, int *displs,
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, r, rsize;
int res, rsize;
MPI_Aint rcvext;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(MPI_SUCCESS != res)) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (NULL == schedule) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* do rsize rounds */
for (r = 0 ; r < rsize ; ++r) {
char *rbuf = ((char *)recvbuf) + (displs[r]*rcvext);
for (int r = 0 ; r < rsize ; ++r) {
char *rbuf = (char *) recvbuf + displs[r] * rcvext;
if (recvcounts[r]) {
res = NBC_Sched_recv(rbuf, false, recvcounts[r], recvtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (rbuf, false, recvcounts[r], recvtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
if (sendcount) {
for (r = 0 ; r < rsize ; ++r) {
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int r = 0 ; r < rsize ; ++r) {
res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -18,25 +19,31 @@
#include <assert.h>
static inline int allred_sched_diss(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf, MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int allred_sched_ring(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf, MPI_Op op, int size, int ext, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int allred_sched_linear(int rank, int p, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int allred_sched_diss(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf,
void *recvbuf, MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int allred_sched_ring(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf,
void *recvbuf, MPI_Op op, int size, int ext, NBC_Schedule *schedule,
NBC_Handle *handle);
static inline int allred_sched_linear(int rank, int p, void *sendbuf, void *recvbuf, int count,
MPI_Datatype datatype, MPI_Op op, int ext, int size,
NBC_Schedule *schedule, NBC_Handle *handle);
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Allreduce_args_compare(NBC_Allreduce_args *a, NBC_Allreduce_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->recvbuf == b->recvbuf) &&
(a->count == b->count) &&
(a->datatype == b->datatype) &&
(a->op == b->op) ) {
return 0;
(a->op == b->op)) {
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if( a->sendbuf < b->sendbuf ) {
return -1;
}
return +1;
}
return 1;
}
#endif
@ -54,29 +61,43 @@ int ompi_coll_libnbc_iallreduce(void* sendbuf, void* recvbuf, int count, MPI_Dat
enum { NBC_ARED_BINOMIAL, NBC_ARED_RING } alg;
char inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = ompi_datatype_get_extent(datatype, &lb, &ext);
if (OMPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (OMPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = ompi_datatype_type_size (datatype, &size);
if (OMPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (OMPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
handle->tmpbuf = malloc(ext*count);
if(handle->tmpbuf == NULL) { printf("Error in malloc() (%i)\n", res); return NBC_OOR; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if((p == 1) && !inplace) {
handle->tmpbuf = malloc (ext * count);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
if ((p == 1) && !inplace) {
/* for a single node - copy data to receivebuf */
res = NBC_Copy(sendbuf, count, datatype, recvbuf, count, datatype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
/* algorithm selection */
@ -88,19 +109,22 @@ int ompi_coll_libnbc_iallreduce(void* sendbuf, void* recvbuf, int count, MPI_Dat
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.recvbuf=recvbuf;
search.count=count;
search.datatype=datatype;
search.op=op;
found = (NBC_Allreduce_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLREDUCE], &search);
if(found == NULL) {
search.sendbuf = sendbuf;
search.recvbuf = recvbuf;
search.count = count;
search.datatype = datatype;
search.op = op;
found = (NBC_Allreduce_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLREDUCE], &search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (NULL == schedule) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* ensure the schedule is released with the handle on error */
handle->schedule = schedule;
switch(alg) {
case NBC_ARED_BINOMIAL:
@ -110,37 +134,59 @@ int ompi_coll_libnbc_iallreduce(void* sendbuf, void* recvbuf, int count, MPI_Dat
res = allred_sched_ring(rank, p, count, datatype, sendbuf, recvbuf, op, size, ext, schedule, handle);
break;
}
if (NBC_OK != res) { printf("Error in Schedule creation() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Allreduce_args*)malloc(sizeof(NBC_Allreduce_args));
args->sendbuf=sendbuf;
args->recvbuf=recvbuf;
args->count=count;
args->datatype=datatype;
args->op=op;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLREDUCE], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_ALLREDUCE] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLREDUCE], &handle->comminfo->NBC_Dict_size[NBC_ALLREDUCE]);
args = (NBC_Allreduce_args *) malloc (sizeof(args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->recvbuf = recvbuf;
args->count = count;
args->datatype = datatype;
args->op = op;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLREDUCE], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_ALLREDUCE] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLREDUCE],
&libnbc_module->NBC_Dict_size[NBC_ALLREDUCE]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_iallreduce_inter(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype, MPI_Op op,
@ -151,41 +197,66 @@ int ompi_coll_libnbc_iallreduce_inter(void* sendbuf, void* recvbuf, int count, M
MPI_Aint ext;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
rsize = ompi_comm_remote_size (comm);
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_size(datatype, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
handle->tmpbuf = malloc(ext*count);
if(handle->tmpbuf == NULL) { printf("Error in malloc() (%i)\n", res); return NBC_OOR; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
handle->tmpbuf = malloc (ext * count);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = allred_sched_linear(rank, rsize, sendbuf, recvbuf, count, datatype, op, ext, size, schedule, handle);
if (NBC_OK != res) { printf("Error in Schedule creation() (%i)\n", res); return res; }
/* ensure the schedule is released with the handle on error */
handle->schedule = schedule;
res = allred_sched_linear (rank, rsize, sendbuf, recvbuf, count, datatype, op,
ext, size, schedule, handle);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Start(handle, schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}
@ -224,50 +295,56 @@ int ompi_coll_libnbc_iallreduce_inter(void* sendbuf, void* recvbuf, int count, M
if (vrank == 0) rank = root; \
if (vrank == root) rank = 0; \
}
static inline int allred_sched_diss(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf, MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle) {
int root, vrank, r, maxr, firstred, vpeer, peer, res;
static inline int allred_sched_diss(int rank, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf,
MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle) {
int root, vrank, maxr, vpeer, peer, res;
root = 0; /* this makes the code for ireduce and iallreduce nearly identical - could be changed to improve performance */
RANK2VRANK(rank, vrank, root);
maxr = (int)ceil((log((double)p)/LOG2));
firstred = 1;
for(r=1; r<=maxr; r++) {
if((vrank % (1<<r)) == 0) {
for (int r = 1, firstred = 1 ; r <= maxr ; ++r) {
if ((vrank % (1 << r)) == 0) {
/* we have to receive this round */
vpeer = vrank + (1<<(r-1));
vpeer = vrank + (1 << (r - 1));
VRANK2RANK(peer, vpeer, root)
if(peer<p) {
res = NBC_Sched_recv(0, true, count, datatype, peer, schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (peer < p) {
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if(firstred && MPI_IN_PLACE != sendbuf) {
res = NBC_Sched_recv (0, true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* this cannot be done until handle->tmpbuf is unused :-( so barrier after the op */
if (firstred && MPI_IN_PLACE != sendbuf) {
/* perform the reduce with the senbuf */
res = NBC_Sched_op(recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule, true);
firstred = 0;
} else {
/* perform the reduce in my local buffer */
res = NBC_Sched_op(recvbuf, false, recvbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (recvbuf, false, recvbuf, false, 0, true, count, datatype, op, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
} else {
/* we have to send this round */
vpeer = vrank - (1<<(r-1));
vpeer = vrank - (1 << (r - 1));
VRANK2RANK(peer, vpeer, root)
if(firstred && MPI_IN_PLACE != sendbuf) {
if (firstred && MPI_IN_PLACE != sendbuf) {
/* we have to use the sendbuf in the first round .. */
res = NBC_Sched_send(sendbuf, false, count, datatype, peer, schedule);
res = NBC_Sched_send (sendbuf, false, count, datatype, peer, schedule, false);
} else {
/* and the recvbuf in all remeining rounds */
res = NBC_Sched_send(recvbuf, false, count, datatype, peer, schedule);
res = NBC_Sched_send (recvbuf, false, count, datatype, peer, schedule, false);
}
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* leave the game */
break;
}
@ -278,61 +355,75 @@ static inline int allred_sched_diss(int rank, int p, int count, MPI_Datatype dat
RANK2VRANK(rank, vrank, root);
/* receive from the right hosts */
if(vrank != 0) {
for(r=0; r<maxr; r++) {
if((vrank >= (1<<r)) && (vrank < (1<<(r+1)))) {
VRANK2RANK(peer, vrank-(1<<r), root);
res = NBC_Sched_recv(recvbuf, false, count, datatype, peer, schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (vrank != 0) {
for (int r = 0; r < maxr ; ++r) {
if ((vrank >= (1 << r)) && (vrank < (1 << (r + 1)))) {
VRANK2RANK(peer, vrank - (1 << r), root);
res = NBC_Sched_recv (recvbuf, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
res = NBC_Sched_barrier(schedule);
if(NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
/* now send to the right hosts */
for(r=0; r<maxr; r++) {
if(((vrank + (1<<r) < p) && (vrank < (1<<r))) || (vrank == 0)) {
VRANK2RANK(peer, vrank+(1<<r), root);
res = NBC_Sched_send(recvbuf, false, count, datatype, peer, schedule);
if(res != NBC_OK) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int r = 0; r < maxr; ++r) {
if (((vrank + (1 << r) < p) && (vrank < (1 << r))) || (vrank == 0)) {
VRANK2RANK(peer, vrank + (1 << r), root);
res = NBC_Sched_send (recvbuf, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
/* end of the bcast */
return NBC_OK;
/* end of the bcast */
return OMPI_SUCCESS;
}
static inline int allred_sched_ring(int r, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf, MPI_Op op, int size, int ext, NBC_Schedule *schedule, NBC_Handle *handle) {
int i; /* runner */
static inline int allred_sched_ring (int r, int p, int count, MPI_Datatype datatype, void *sendbuf, void *recvbuf, MPI_Op op,
int size, int ext, NBC_Schedule *schedule, NBC_Handle *handle) {
int segsize, *segsizes, *segoffsets; /* segment sizes and offsets per segment (number of segments == number of nodes */
int speer, rpeer; /* send and recvpeer */
int res = OMPI_SUCCESS;
if(count == 0) return NBC_OK;
if (count == 0) {
return OMPI_SUCCESS;
}
{
int mycount; /* temporary */
segsizes = (int*)malloc(sizeof(int)*p);
segoffsets = (int*)malloc(sizeof(int)*p);
segsize = count/p; /* size of the segments */
if(count%p != 0) segsize++;
mycount = count;
segoffsets[0] = 0;
for(i = 0; i<p;i++) {
mycount -= segsize;
segsizes[i] = segsize;
if(mycount < 0) {
segsizes[i] = segsize+mycount;
mycount = 0;
}
if(i) segoffsets[i] = segoffsets[i-1] + segsizes[i-1];
/*if(!r) printf("count: %i, (%i) size: %i, offset: %i\n", count, i, segsizes[i], segoffsets[i]); */
segsizes = (int *) malloc (sizeof (int) * p);
segoffsets = (int *) malloc (sizeof (int) * p);
if (NULL == segsizes || NULL == segoffsets) {
free (segsizes);
free (segoffsets);
return OMPI_ERR_OUT_OF_RESOURCE;
}
segsize = (count + p - 1) / p; /* size of the segments */
segoffsets[0] = 0;
for (int i = 0, mycount = count ; i < p ; ++i) {
mycount -= segsize;
segsizes[i] = segsize;
if (mycount < 0) {
segsizes[i] = segsize + mycount;
mycount = 0;
}
if (i) {
segoffsets[i] = segoffsets[i-1] + segsizes[i-1];
}
}
/* reduce peers */
speer = (r+1)%p;
rpeer = (r-1+p)%p;
speer = (r + 1) % p;
rpeer = (r - 1 + p) % p;
/* + -> reduced this round
* / -> sum (reduced in a previous step)
@ -432,96 +523,131 @@ static inline int allred_sched_ring(int r, int p, int count, MPI_Datatype dataty
* 2p-2 rounds ... every node does p-1 reductions and p-1 sends
*
*/
{
int round = 0;
/* first p-1 rounds are reductions */
do {
int selement = (r+1-round + 2*p /*2*p avoids negative mod*/)%p; /* the element I am sending */
int soffset = segoffsets[selement]*ext;
int relement = (r-round + 2*p /*2*p avoids negative mod*/)%p; /* the element that I receive from my neighbor */
int roffset = segoffsets[relement]*ext;
/* first p-1 rounds are reductions */
for (int round = 0 ; round < p - 1 ; ++round) {
int selement = (r+1-round + 2*p /*2*p avoids negative mod*/)%p; /* the element I am sending */
int soffset = segoffsets[selement]*ext;
int relement = (r-round + 2*p /*2*p avoids negative mod*/)%p; /* the element that I receive from my neighbor */
int roffset = segoffsets[relement]*ext;
/* first message come out of sendbuf */
if(round == 0) {
NBC_Sched_send((char*)sendbuf+soffset, false, segsizes[selement], datatype, speer, schedule);
} else {
NBC_Sched_send((char*)recvbuf+soffset, false, segsizes[selement], datatype, speer, schedule);
}
NBC_Sched_recv((char*)recvbuf+roffset, false, segsizes[relement], datatype, rpeer, schedule);
/* first message come out of sendbuf */
if (round == 0) {
res = NBC_Sched_send ((char *) sendbuf + soffset, false, segsizes[selement], datatype, speer,
schedule, false);
} else {
res = NBC_Sched_send ((char *) recvbuf + soffset, false, segsizes[selement], datatype, speer,
schedule, false);
}
NBC_Sched_barrier(schedule);
NBC_Sched_op((char*)recvbuf+roffset, false, (char*)sendbuf+roffset, false, (char*)recvbuf+roffset, false, segsizes[relement], datatype, op, schedule);
NBC_Sched_barrier(schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
round++;
} while(round < p-1);
res = NBC_Sched_recv ((char *) recvbuf + roffset, false, segsizes[relement], datatype, rpeer,
schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
do {
int selement = (r+1-round + 2*p /*2*p avoids negative mod*/)%p; /* the element I am sending */
int soffset = segoffsets[selement]*ext;
int relement = (r-round + 2*p /*2*p avoids negative mod*/)%p; /* the element that I receive from my neighbor */
int roffset = segoffsets[relement]*ext;
NBC_Sched_send((char*)recvbuf+soffset, false, segsizes[selement], datatype, speer, schedule);
NBC_Sched_recv((char*)recvbuf+roffset, false, segsizes[relement], datatype, rpeer, schedule);
NBC_Sched_barrier(schedule);
round++;
} while (round < 2*p-2);
res = NBC_Sched_op ((char *) recvbuf + roffset, false, (char *) sendbuf + roffset, false,
(char *) recvbuf + roffset, false, segsizes[relement], datatype, op, schedule,
true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
return NBC_OK;
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
free (segsizes);
free (segoffsets);
return res;
}
for (int round = p - 1 ; round < 2 * p - 2 ; ++round) {
int selement = (r+1-round + 2*p /*2*p avoids negative mod*/)%p; /* the element I am sending */
int soffset = segoffsets[selement]*ext;
int relement = (r-round + 2*p /*2*p avoids negative mod*/)%p; /* the element that I receive from my neighbor */
int roffset = segoffsets[relement]*ext;
res = NBC_Sched_send ((char *) recvbuf + soffset, false, segsizes[selement], datatype, speer,
schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
res = NBC_Sched_recv ((char *) recvbuf + roffset, false, segsizes[relement], datatype, rpeer,
schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
free (segsizes);
free (segoffsets);
return res;
}
static inline int allred_sched_linear(int rank, int rsize, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle) {
int res, rpeer;
int res;
if(count == 0) return NBC_OK;
if (0 == count) {
return OMPI_SUCCESS;
}
/* send my data to the remote root */
res = NBC_Sched_send (sendbuf, false, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sendbuf, false, count, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
res = NBC_Sched_recv (recvbuf, false, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (recvbuf, false, count, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if (0 == rank) {
/* wait for data from the remote root */
res = NBC_Sched_barrier (schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* get data from remote peers and reduce */
for (rpeer = 1 ; rpeer < rsize ; ++rpeer) {
res = NBC_Sched_recv (0, true, count, datatype, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
for (int rpeer = 1 ; rpeer < rsize ; ++rpeer) {
res = NBC_Sched_recv (0, true, count, datatype, rpeer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_op (recvbuf, false, 0, true, recvbuf, false, count, datatype, op, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_op (recvbuf, false, 0, true, recvbuf, false, count, datatype, op,
schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
/* exchange our result with the remote root (each root will broadcast to the other's peers) */
res = NBC_Sched_recv (0, true, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_send (recvbuf, false, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_recv (0, true, count, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* wait for data from remote root */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_send (recvbuf, false, count, datatype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* broadcast the result to all remote peers */
for (rpeer = 1 ; rpeer < rsize ; ++rpeer) {
res = NBC_Sched_send (0, true, count, datatype, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int rpeer = 1 ; rpeer < rsize ; ++rpeer) {
res = NBC_Sched_send (0, true, count, datatype, rpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
@ -15,26 +16,33 @@
*/
#include "nbc_internal.h"
static inline int a2a_sched_linear(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule *schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
static inline int a2a_sched_pairwise(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule *schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
static inline int a2a_sched_diss(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, NBC_Handle *handle);
static inline int a2a_sched_linear(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule *schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
static inline int a2a_sched_pairwise(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule *schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int recvcount, MPI_Datatype recvtype, MPI_Comm comm);
static inline int a2a_sched_diss(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int recvcount, MPI_Datatype recvtype, MPI_Comm comm, NBC_Handle *handle);
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Alltoall_args_compare(NBC_Alltoall_args *a, NBC_Alltoall_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->sendcount == b->sendcount) &&
(a->sendtype == b->sendtype) &&
(a->recvbuf == b->recvbuf) &&
(a->recvcount == b->recvcount) &&
(a->recvtype == b->recvtype) ) {
return 0;
(a->recvtype == b->recvtype)) {
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if( a->sendbuf < b->sendbuf ) {
return -1;
}
return +1;
}
return 1;
}
#endif
@ -52,27 +60,33 @@ int ompi_coll_libnbc_ialltoall(void* sendbuf, int sendcount, MPI_Datatype sendty
char *rbuf, *sbuf, inplace;
enum {NBC_A2A_LINEAR, NBC_A2A_PAIRWISE, NBC_A2A_DISS} alg;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_size(sendtype, &sndsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
/* algorithm selection */
a2asize = sndsize*sendcount*p;
a2asize = sndsize * sendcount * p;
/* this number is optimized for TCP on odin.cs.indiana.edu */
if((p <= 8) && ((a2asize < 1<<17) || (sndsize*sendcount < 1<<12))) {
/* just send as fast as we can if we have less than 8 peers, if the
@ -85,73 +99,104 @@ int ompi_coll_libnbc_ialltoall(void* sendbuf, int sendcount, MPI_Datatype sendty
} else
alg = NBC_A2A_LINEAR; /*NBC_A2A_PAIRWISE;*/
if(!inplace) {
if (!inplace) {
/* copy my data to receive buffer */
rbuf = ((char *)recvbuf) + (rank*recvcount*rcvext);
sbuf = ((char *)sendbuf) + (rank*sendcount*sndext);
res = NBC_Copy(sbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
rbuf = (char *) recvbuf + rank * recvcount * rcvext;
sbuf = (char *) sendbuf + rank * sendcount * sndext;
res = NBC_Copy (sbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* allocate temp buffer if we need one */
if(alg == NBC_A2A_DISS) {
if (alg == NBC_A2A_DISS) {
/* only A2A_DISS needs buffers */
if(NBC_Type_intrinsic(sendtype)) {
datasize = sndext*sendcount;
datasize = sndext * sendcount;
} else {
res = MPI_Pack_size(sendcount, sendtype, comm, &datasize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack_size() (%i)\n", res); return res; }
res = MPI_Pack_size (sendcount, sendtype, comm, &datasize);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Pack_size() (%i)", res);
NBC_Return_handle (handle);
return res;
}
}
/* allocate temporary buffers */
if(p % 2 == 0) {
handle->tmpbuf=malloc(datasize*p*2);
if ((p & 1) == 0) {
handle->tmpbuf = malloc (datasize * p * 2);
} else {
/* we cannot divide p by two, so alloc more to be safe ... */
handle->tmpbuf=malloc(datasize*(p/2+1)*2*2);
handle->tmpbuf = malloc (datasize * (p / 2 + 1) * 2 * 2);
}
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* phase 1 - rotate n data blocks upwards into the tmpbuffer */
#if OPAL_CUDA_SUPPORT
if(NBC_Type_intrinsic(sendtype) && !(opal_cuda_check_bufs((char *)sendbuf, (char *)recvbuf))) {
if (NBC_Type_intrinsic(sendtype) && !(opal_cuda_check_bufs((char *)sendbuf, (char *)recvbuf))) {
#else
if(NBC_Type_intrinsic(sendtype)) {
if (NBC_Type_intrinsic(sendtype)) {
#endif /* OPAL_CUDA_SUPPORT */
/* contiguous - just copy (1st copy) */
memcpy(handle->tmpbuf, (char*)sendbuf+datasize*rank, datasize*(p-rank));
if(rank != 0) memcpy((char*)handle->tmpbuf+datasize*(p-rank), sendbuf, datasize*(rank));
memcpy (handle->tmpbuf, (char *) sendbuf + datasize * rank, datasize * (p - rank));
if (rank != 0) {
memcpy ((char *) handle->tmpbuf + datasize * (p - rank), sendbuf, datasize * rank);
}
} else {
int pos=0;
/* non-contiguous - pack */
res = MPI_Pack((char*)sendbuf+rank*sendcount*sndext, (p-rank)*sendcount, sendtype, handle->tmpbuf, (p-rank)*datasize, &pos, comm);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack() (%i)\n", res); return res; }
if(rank != 0) {
res = MPI_Pack ((char *) sendbuf + rank * sendcount * sndext, (p - rank) * sendcount, sendtype, handle->tmpbuf,
(p - rank) * datasize, &pos, comm);
if (OPAL_UNLIKELY(MPI_SUCCESS != res)) {
NBC_Error("MPI Error in MPI_Pack() (%i)", res);
NBC_Return_handle (handle);
return res;
}
if (rank != 0) {
pos = 0;
MPI_Pack(sendbuf, rank*sendcount, sendtype, (char*)handle->tmpbuf+datasize*(p-rank), rank*datasize, &pos, comm);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack() (%i)\n", res); return res; }
res = MPI_Pack(sendbuf, rank * sendcount, sendtype, (char *) handle->tmpbuf + datasize * (p - rank),
rank * datasize, &pos, comm);
if (OPAL_UNLIKELY(MPI_SUCCESS != res)) {
NBC_Error("MPI Error in MPI_Pack() (%i)", res);
NBC_Return_handle (handle);
return res;
}
}
}
} else {
handle->tmpbuf=NULL;
}
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.sendcount=sendcount;
search.sendtype=sendtype;
search.recvbuf=recvbuf;
search.recvcount=recvcount;
search.recvtype=recvtype;
found = (NBC_Alltoall_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLTOALL], &search);
if(found == NULL) {
search.sendbuf = sendbuf;
search.sendcount = sendcount;
search.sendtype = sendtype;
search.recvbuf = recvbuf;
search.recvcount = recvcount;
search.recvtype = recvtype;
found = (NBC_Alltoall_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLTOALL], &search);
if (NULL == found) {
#endif
/* not found - generate new schedule */
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* ensure the schedule is released with the handle on error */
handle->schedule = schedule;
switch(alg) {
case NBC_A2A_LINEAR:
@ -165,205 +210,272 @@ int ompi_coll_libnbc_ialltoall(void* sendbuf, int sendcount, MPI_Datatype sendty
break;
}
if (NBC_OK != res) { return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Alltoall_args*)malloc(sizeof(NBC_Alltoall_args));
args->sendbuf=sendbuf;
args->sendcount=sendcount;
args->sendtype=sendtype;
args->recvbuf=recvbuf;
args->recvcount=recvcount;
args->recvtype=recvtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLTOALL], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_ALLTOALL] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_ALLTOALL], &handle->comminfo->NBC_Dict_size[NBC_ALLTOALL]);
/*if(!rank) printf("[%i] removing %i elements - new size: %i \n", rank, SCHED_DICT_UPPER-SCHED_DICT_LOWER, handle->comminfo->NBC_Alltoall_size);*/
args = (NBC_Alltoall_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->sendcount = sendcount;
args->sendtype = sendtype;
args->recvbuf = recvbuf;
args->recvcount = recvcount;
args->recvtype = recvtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLTOALL], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_ALLTOALL] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_ALLTOALL],
&libnbc_module->NBC_Dict_size[NBC_ALLTOALL]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
/*if(!rank) printf("[%i] added new schedule to tree - number %i\n", rank, handle->comminfo->NBC_Dict_size[NBC_ALLTOALL]);*/
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_ialltoall_inter (void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, i, rsize;
int res, rsize;
MPI_Aint sndext, rcvext;
NBC_Schedule *schedule;
char *rbuf, *sbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
rsize = ompi_comm_remote_size (comm);
res = MPI_Comm_remote_size (comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
for (i = 0; i < rsize; i++) {
/* post all sends */
sbuf = ((char *) sendbuf) + (i * sendcount * sndext);
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
/* post all receives */
rbuf = ((char *) recvbuf) + (i * recvcount * rcvext);
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = MPI_Type_extent (sendtype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
/*NBC_PRINT_SCHED(*schedule);*/
res = MPI_Type_extent (recvtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
for (int i = 0; i < rsize; i++) {
/* post all sends */
sbuf = (char *) sendbuf + i * sendcount * sndext;
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
return NBC_OK;
}
static inline int a2a_sched_pairwise(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) {
int res, r, sndpeer, rcvpeer;
char *rbuf, *sbuf;
res = NBC_OK;
if(p < 2) return res;
for(r=1;r<p;r++) {
sndpeer = (rank+r)%p;
rcvpeer = (rank-r+p)%p;
rbuf = ((char *) recvbuf) + (rcvpeer*recvcount*rcvext);
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, rcvpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
sbuf = ((char *) sendbuf) + (sndpeer*sendcount*sndext);
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, sndpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (r < p) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barr() (%i)\n", res); return res; }
/* post all receives */
rbuf = (char *) recvbuf + i * recvcount * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
return res;
}
static inline int a2a_sched_linear(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm) {
int res, r;
char *rbuf, *sbuf;
res = NBC_OK;
for(r=0;r<p;r++) {
/* easy algorithm */
if (r == rank) { continue; }
rbuf = ((char *) recvbuf) + (r*recvcount*rcvext);
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
sbuf = ((char *) sendbuf) + (r*sendcount*sndext);
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, r, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return res;
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
static inline int a2a_sched_diss(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule, void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount, MPI_Datatype recvtype, MPI_Comm comm, NBC_Handle *handle) {
int res, i, r, speer, rpeer, datasize, offset, virtp;
static inline int a2a_sched_pairwise(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm) {
int res;
if (p < 2) {
return OMPI_SUCCESS;
}
for (int r = 1 ; r < p ; ++r) {
int sndpeer = (rank + r) % p;
int rcvpeer = (rank - r + p) % p;
char *rbuf = (char *) recvbuf + rcvpeer * recvcount * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, rcvpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
char *sbuf = (char *) sendbuf + sndpeer * sendcount * sndext;
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, sndpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if (r < p) {
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
return OMPI_SUCCESS;
}
static inline int a2a_sched_linear(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm) {
int res;
for (int r = 0 ; r < p ; ++r) {
/* easy algorithm */
if (r == rank) {
continue;
}
char *rbuf = (char *) recvbuf + r * recvcount * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
char *sbuf = (char *) sendbuf + r * sendcount * sndext;
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
return OMPI_SUCCESS;
}
static inline int a2a_sched_diss(int rank, int p, MPI_Aint sndext, MPI_Aint rcvext, NBC_Schedule* schedule,
void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, MPI_Comm comm, NBC_Handle *handle) {
int res, speer, rpeer, datasize, offset, virtp;
char *rbuf, *rtmpbuf, *stmpbuf;
res = NBC_OK;
if(p < 2) return res;
if (p < 2) {
return OMPI_SUCCESS;
}
if(NBC_Type_intrinsic(sendtype)) {
datasize = sndext*sendcount;
} else {
res = MPI_Pack_size(sendcount, sendtype, comm, &datasize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Pack_size() (%i)", res);
return res;
}
}
/* allocate temporary buffers */
if(p % 2 == 0) {
rtmpbuf = (char*)handle->tmpbuf+datasize*p;
stmpbuf = (char*)handle->tmpbuf+datasize*(p+p/2);
if ((p & 1) == 0) {
rtmpbuf = (char *) handle->tmpbuf + datasize * p;
stmpbuf = (char *) handle->tmpbuf + datasize * (p + p / 2);
} else {
/* we cannot divide p by two, so alloc more to be safe ... */
virtp = (p/2+1)*2;
rtmpbuf = (char*)handle->tmpbuf+datasize*p;
stmpbuf = (char*)handle->tmpbuf+datasize*(p+virtp/2);
virtp = (p / 2 + 1) * 2;
rtmpbuf = (char *) handle->tmpbuf + datasize * p;
stmpbuf = (char *) handle->tmpbuf + datasize * (p + virtp / 2);
}
/* phase 2 - communicate */
/*printf("[%i] temp buffer is at %lu of size %i, maxround: %i\n", rank, (unsigned long)handle->tmpbuf, (int)datasize*p*(1<<maxround), maxround);*/
for(r = 1; r < p; r<<=1) {
for (int r = 1; r < p; r <<= 1) {
offset = 0;
for(i=1; i<p; i++) {
for (int i = 1 ; i < p; ++i) {
/* test if bit r is set in rank number i */
if((i&r) == r) {
if (i & r) {
/* copy data to sendbuffer (2nd copy) - could be avoided using iovecs */
/*printf("[%i] round %i: copying element %i to buffer %lu\n", rank, r, i, (unsigned long)(stmpbuf+offset));*/
NBC_Sched_copy((void*)(long)(i*datasize), true, datasize, MPI_BYTE, stmpbuf+offset-(unsigned long)handle->tmpbuf, true, datasize, MPI_BYTE, schedule);
res = NBC_Sched_copy((void *)(intptr_t)(i * datasize), true, datasize, MPI_BYTE, stmpbuf + offset -
(intptr_t) handle->tmpbuf, true, datasize, MPI_BYTE, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
offset += datasize;
}
}
speer = ( rank + r) % p;
speer = (rank + r) % p;
/* add p because modulo does not work with negative values */
rpeer = ((rank - r)+p) % p;
rpeer = ((rank - r) + p) % p;
/*printf("[%i] receiving %i bytes from host %i into rbuf %lu\n", rank, offset, rpeer, (unsigned long)rtmpbuf);*/
res = NBC_Sched_recv(rtmpbuf-(unsigned long)handle->tmpbuf, true, offset, MPI_BYTE, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (rtmpbuf - (intptr_t) handle->tmpbuf, true, offset, MPI_BYTE, rpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/*printf("[%i] sending %i bytes to host %i from sbuf %lu\n", rank, offset, speer, (unsigned long)stmpbuf);*/
res = NBC_Sched_send(stmpbuf-(unsigned long)handle->tmpbuf, true, offset, MPI_BYTE, speer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_send (stmpbuf - (intptr_t) handle->tmpbuf, true, offset, MPI_BYTE, speer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* unpack from buffer */
offset = 0;
for(i=1; i<p; i++) {
for (int i = 1; i < p; ++i) {
/* test if bit r is set in rank number i */
if((i&r) == r) {
if (i & r) {
/* copy data to tmpbuffer (3rd copy) - could be avoided using iovecs */
NBC_Sched_copy(rtmpbuf+offset-(unsigned long)handle->tmpbuf, true, datasize, MPI_BYTE, (void*)(long)(i*datasize), true, datasize, MPI_BYTE, schedule);
res = NBC_Sched_copy (rtmpbuf + offset - (intptr_t) handle->tmpbuf, true, datasize, MPI_BYTE,
(void *)(intptr_t)(i * datasize), true, datasize, MPI_BYTE, schedule,
false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
offset += datasize;
}
}
@ -371,12 +483,15 @@ static inline int a2a_sched_diss(int rank, int p, MPI_Aint sndext, MPI_Aint rcve
/* phase 3 - reorder - data is now in wrong order in handle->tmpbuf -
* reorder it into recvbuf */
for(i=0; i<p; i++) {
rbuf = (char*)recvbuf+((rank-i+p)%p)*recvcount*rcvext;
res = NBC_Sched_unpack((void*)(long)(i*datasize), true, recvcount, recvtype, rbuf, false, schedule);
if (NBC_OK != res) { printf("MPI Error in NBC_Sched_pack() (%i)\n", res); return res; }
for (int i = 0 ; i < p; ++i) {
rbuf = (char *) recvbuf + ((rank - i + p) % p) * recvcount * rcvext;
res = NBC_Sched_unpack ((void *)(intptr_t) (i * datasize), true, recvcount, recvtype, rbuf, false, schedule,
false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -20,71 +23,95 @@
int ompi_coll_libnbc_ialltoallv(void* sendbuf, int *sendcounts, int *sdispls,
MPI_Datatype sendtype, void* recvbuf, int *recvcounts, int *rdispls,
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, p, res, i;
int rank, p, res;
MPI_Aint sndext, rcvext;
NBC_Schedule *schedule;
char *rbuf, *sbuf, inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res= MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
res = MPI_Type_extent (sendtype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
res = MPI_Type_extent (recvtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
/* copy data to receivbuffer */
if((sendcounts[rank] != 0) && !inplace) {
rbuf = ((char *) recvbuf) + (rdispls[rank] * rcvext);
sbuf = ((char *) sendbuf) + (sdispls[rank] * sndext);
res = NBC_Copy(sbuf, sendcounts[rank], sendtype, rbuf, recvcounts[rank], recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
if ((sendcounts[rank] != 0) && !inplace) {
rbuf = (char *) recvbuf + rdispls[rank] * rcvext;
sbuf = (char *) sendbuf + sdispls[rank] * sndext;
res = NBC_Copy (sbuf, sendcounts[rank], sendtype, rbuf, recvcounts[rank], recvtype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
for (i = 0; i < p; i++) {
if (i == rank) { continue; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
for (int i = 0 ; i < p ; ++i) {
if (i == rank) {
continue;
}
/* post all sends */
if(sendcounts[i] != 0) {
if (sendcounts[i] != 0) {
sbuf = ((char *) sendbuf) + (sdispls[i] * sndext);
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
/* post all receives */
if(recvcounts[i] != 0) {
if (recvcounts[i] != 0) {
rbuf = ((char *) recvbuf) + (rdispls[i] * rcvext);
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
/* simple linear Alltoallv */
@ -93,56 +120,74 @@ int ompi_coll_libnbc_ialltoallv_inter (void* sendbuf, int *sendcounts, int *sdis
MPI_Datatype recvtype, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, i, rsize;
int res, rsize;
MPI_Aint sndext, rcvext;
NBC_Schedule *schedule;
char *rbuf, *sbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
MPI_Comm_remote_size (comm, &rsize);
rsize = ompi_comm_remote_size (comm);
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
for (i = 0; i < rsize; i++) {
for (int i = 0; i < rsize; i++) {
/* post all sends */
if(sendcounts[i] != 0) {
sbuf = ((char *) sendbuf) + (sdispls[i] * sndext);
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (sendcounts[i] != 0) {
sbuf = (char *) sendbuf + sdispls[i] * sndext;
res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
/* post all receives */
if(recvcounts[i] != 0) {
rbuf = ((char *) recvbuf) + (rdispls[i] * rcvext);
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (recvcounts[i] != 0) {
rbuf = (char *) recvbuf + rdispls[i] * rcvext;
res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -22,64 +25,78 @@ int ompi_coll_libnbc_ialltoallw(void* sendbuf, int *sendcounts, int *sdispls,
MPI_Datatype recvtypes[], struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, p, res, i;
int rank, p, res;
NBC_Schedule *schedule;
char *rbuf, *sbuf, inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res= MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
/* copy data to receivbuffer */
if((sendcounts[rank] != 0) && !inplace) {
rbuf = ((char *) recvbuf) + rdispls[rank];
sbuf = ((char *) sendbuf) + sdispls[rank];
if ((sendcounts[rank] != 0) && !inplace) {
rbuf = (char *) recvbuf + rdispls[rank];
sbuf = (char *) sendbuf + sdispls[rank];
res = NBC_Copy(sbuf, sendcounts[rank], sendtypes[rank], rbuf, recvcounts[rank], recvtypes[rank], comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
for (i = 0; i < p; i++) {
if (i == rank) { continue; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
for (int i = 0; i < p; i++) {
if (i == rank) {
continue;
}
/* post all sends */
if(sendcounts[i] != 0) {
sbuf = ((char *) sendbuf) + sdispls[i];
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtypes[i], i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (sendcounts[i] != 0) {
sbuf = (char *) sendbuf + sdispls[i];
res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtypes[i], i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
/* post all receives */
if(recvcounts[i] != 0) {
rbuf = ((char *) recvbuf) + rdispls[i];
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtypes[i], i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (recvcounts[i] != 0) {
rbuf = (char *) recvbuf + rdispls[i];
res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtypes[i], i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
/* simple linear Alltoallw */
@ -88,51 +105,59 @@ int ompi_coll_libnbc_ialltoallw_inter (void* sendbuf, int *sendcounts, int *sdis
MPI_Datatype recvtypes[], struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, i, rsize;
int res, rsize;
NBC_Schedule *schedule;
char *rbuf, *sbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
MPI_Comm_remote_size (comm, &rsize);
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
for (i = 0; i < rsize; i++) {
for (int i = 0 ; i < rsize ; ++i) {
/* post all sends */
if(sendcounts[i] != 0) {
sbuf = ((char *) sendbuf) + sdispls[i];
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtypes[i], i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (sendcounts[i] != 0) {
sbuf = (char *) sendbuf + sdispls[i];
res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtypes[i], i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
/* post all receives */
if(recvcounts[i] != 0) {
rbuf = ((char *) recvbuf) + rdispls[i];
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtypes[i], i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (recvcounts[i] != 0) {
rbuf = (char *) recvbuf + rdispls[i];
res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtypes[i], i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -18,137 +19,186 @@
int ompi_coll_libnbc_ibarrier(struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int round, rank, p, maxround, res, recvpeer, sendpeer;
int rank, p, maxround, res, recvpeer, sendpeer;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
handle->tmpbuf=(void*)malloc(2*sizeof(char));
handle->tmpbuf = malloc (2);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
#ifdef NBC_CACHE_SCHEDULE
/* there only one argument set per communicator -> hang it directly at
* the tree-position, NBC_Dict_size[...] is 0 for not initialized and
* 1 for initialized. NBC_Dict[...] is a pointer to the schedule in
* this case */
if(handle->comminfo->NBC_Dict_size[NBC_BARRIER] == 0) {
if (libnbc_module->NBC_Dict_size[NBC_BARRIER] == 0) {
/* we did not init it yet */
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
round = -1;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* ensure the schedule is released with the handle on error */
handle->schedule = schedule;
maxround = (int)ceil((log((double)p)/LOG2)-1);
do {
round++;
sendpeer = (rank + (1<<round)) % p;
for (int round = 0 ; round <= maxround ; ++round) {
sendpeer = (rank + (1 << round)) % p;
/* add p because modulo does not work with negative values */
recvpeer = ((rank - (1<<round))+p) % p;
recvpeer = ((rank - (1 << round)) + p) % p;
/* send msg to sendpeer */
res = NBC_Sched_send((void*)0, true, 1, MPI_BYTE, sendpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send ((void *) 0, true, 1, MPI_BYTE, sendpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* recv msg from recvpeer */
res = NBC_Sched_recv((void*)1, true, 1, MPI_BYTE, recvpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv ((void *) 1, true, 1, MPI_BYTE, recvpeer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* end communication round */
if(round < maxround){
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (round < maxround) {
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
}
} while (round < maxround);
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
#ifdef NBC_CACHE_SCHEDULE
/* add it */
handle->comminfo->NBC_Dict[NBC_BARRIER] = (hb_tree*)schedule;
handle->comminfo->NBC_Dict_size[NBC_BARRIER] = 1;
libnbc_module->NBC_Dict[NBC_BARRIER] = (hb_tree *) schedule;
libnbc_module->NBC_Dict_size[NBC_BARRIER] = 1;
} else {
/* we found it */
schedule = (NBC_Schedule*)handle->comminfo->NBC_Dict[NBC_BARRIER];
handle->schedule = schedule = (NBC_Schedule *) libnbc_module->NBC_Dict[NBC_BARRIER];
}
OBJ_RETAIN(schedule);
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_ibarrier_inter(struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, res, rsize, peer;
int rank, res, rsize;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
rank = ompi_comm_rank (comm);
rsize = ompi_comm_remote_size (comm);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
handle->tmpbuf=(void*)malloc(2*sizeof(char));
handle->tmpbuf = malloc (2);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* ensure the schedule is released with the handle on error */
handle->schedule = schedule;
if (0 == rank) {
for (peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv (0, true, 1, MPI_BYTE, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
for (int peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv (0, true, 1, MPI_BYTE, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
}
}
/* synchronize with the remote root */
res = NBC_Sched_recv (0, true, 1, MPI_BYTE, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (0, true, 1, MPI_BYTE, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_send (0, true, 1, MPI_BYTE, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (0, true, 1, MPI_BYTE, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
if (0 == rank) {
/* wait for the remote root */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* inform remote peers that all local peers have entered the barrier */
for (peer = 0 ; peer < rsize ; ++peer) {
res = NBC_Sched_send (0, true, 1, MPI_BYTE, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int peer = 0 ; peer < rsize ; ++peer) {
res = NBC_Sched_send (0, true, 1, MPI_BYTE, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,36 +7,42 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
*/
#include "nbc_internal.h"
static inline int bcast_sched_binomial(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype);
static inline int bcast_sched_linear(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype);
static inline int bcast_sched_chain(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype, int fragsize, int size);
static inline int bcast_sched_binomial(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count,
MPI_Datatype datatype);
static inline int bcast_sched_linear(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count,
MPI_Datatype datatype);
static inline int bcast_sched_chain(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count,
MPI_Datatype datatype, int fragsize, int size);
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Bcast_args_compare(NBC_Bcast_args *a, NBC_Bcast_args *b, void *param) {
if( (a->buffer == b->buffer) &&
if ((a->buffer == b->buffer) &&
(a->count == b->count) &&
(a->datatype == b->datatype) &&
(a->root == b->root) ) {
return 0;
return 0;
}
if( a->buffer < b->buffer ) {
if( a->buffer < b->buffer ) {
return -1;
}
return +1;
}
return 1;
}
#endif
int ompi_coll_libnbc_ibcast(void *buffer, int count, MPI_Datatype datatype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module)
struct mca_coll_base_module_2_1_0_t *module)
{
int rank, p, res, size, segsize;
NBC_Schedule *schedule;
@ -44,48 +51,44 @@ int ompi_coll_libnbc_ibcast(void *buffer, int count, MPI_Datatype datatype, int
#endif
enum { NBC_BCAST_LINEAR, NBC_BCAST_BINOMIAL, NBC_BCAST_CHAIN } alg;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = MPI_Type_size(datatype, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
segsize = 16384;
/* algorithm selection */
if(p <= 4) {
if (p <= 4) {
alg = NBC_BCAST_LINEAR;
} else if(size*count < 65536) {
} else if (size * count < 65536) {
alg = NBC_BCAST_BINOMIAL;
} else if(size*count < 524288) {
} else if (size * count < 524288) {
alg = NBC_BCAST_CHAIN;
segsize = 16384/2;
segsize = 8192;
} else {
alg = NBC_BCAST_CHAIN;
segsize = 65536/2;
segsize = 32768;
}
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.buffer=buffer;
search.count=count;
search.datatype=datatype;
search.root=root;
found = (NBC_Bcast_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_BCAST], &search);
if(found == NULL) {
search.buffer = buffer;
search.count = count;
search.datatype = datatype;
search.root = root;
found = (NBC_Bcast_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_BCAST], &search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
switch(alg) {
case NBC_BCAST_LINEAR:
@ -98,34 +101,63 @@ int ompi_coll_libnbc_ibcast(void *buffer, int count, MPI_Datatype datatype, int
res = bcast_sched_chain(rank, p, root, schedule, buffer, count, datatype, segsize, size);
break;
}
if (NBC_OK != res) { printf("Error in Schedule creation() (%i)\n", res); return res; }
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Bcast_args*)malloc(sizeof(NBC_Bcast_args));
args->buffer=buffer;
args->count=count;
args->datatype=datatype;
args->root=root;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_BCAST], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_BCAST] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_BCAST], &handle->comminfo->NBC_Dict_size[NBC_BCAST]);
args = (NBC_Bcast_args *) malloc (sizeof (args));
if (NULL != args) {
args->buffer = buffer;
args->count = count;
args->datatype = datatype;
args->root = root;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_BCAST], args, args, 0);
if (0 == res) {
OBJ_RETAIN (schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_BCAST] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_BCAST],
&libnbc_module->NBC_Dict_size[NBC_BCAST]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
/* better binomial bcast
@ -154,62 +186,73 @@ int ompi_coll_libnbc_ibcast(void *buffer, int count, MPI_Datatype datatype, int
if (vrank == root) rank = 0; \
}
static inline int bcast_sched_binomial(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype) {
int maxr, vrank, peer, r, res;
int maxr, vrank, peer, res;
maxr = (int)ceil((log((double)p)/LOG2));
RANK2VRANK(rank, vrank, root);
/* receive from the right hosts */
if(vrank != 0) {
for(r=0; r<maxr; r++) {
if((vrank >= (1<<r)) && (vrank < (1<<(r+1)))) {
VRANK2RANK(peer, vrank-(1<<r), root);
res = NBC_Sched_recv(buffer, false, count, datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (vrank != 0) {
for (int r = 0 ; r < maxr ; ++r) {
if ((vrank >= (1 << r)) && (vrank < (1 << (r + 1)))) {
VRANK2RANK(peer, vrank - (1 << r), root);
res = NBC_Sched_recv (buffer, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
/* now send to the right hosts */
for(r=0; r<maxr; r++) {
if(((vrank + (1<<r) < p) && (vrank < (1<<r))) || (vrank == 0)) {
VRANK2RANK(peer, vrank+(1<<r), root);
res = NBC_Sched_send(buffer, false, count, datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int r = 0 ; r < maxr ; ++r) {
if (((vrank + (1 << r) < p) && (vrank < (1 << r))) || (vrank == 0)) {
VRANK2RANK(peer, vrank + (1 << r), root);
res = NBC_Sched_send (buffer, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
/* simple linear MPI_Ibcast */
static inline int bcast_sched_linear(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype) {
int peer, res;
int res;
/* send to all others */
if(rank == root) {
for (peer=0; peer<p;peer++) {
if(peer != root) {
for (int peer = 0 ; peer < p ; ++peer) {
if (peer != root) {
/* send msg to peer */
res = NBC_Sched_send(buffer, false, count, datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (buffer, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
} else {
/* recv msg from root */
res = NBC_Sched_recv(buffer, false, count, datatype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (buffer, false, count, datatype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
/* simple chained MPI_Ibcast */
static inline int bcast_sched_chain(int rank, int p, int root, NBC_Schedule *schedule, void *buffer, int count, MPI_Datatype datatype, int fragsize, int size) {
int res, vrank, rpeer, speer, numfrag, fragnum, fragcount, thiscount;
int res, vrank, rpeer, speer, numfrag, fragcount, thiscount;
MPI_Aint ext;
char *buf;
@ -217,38 +260,54 @@ static inline int bcast_sched_chain(int rank, int p, int root, NBC_Schedule *sch
VRANK2RANK(rpeer, vrank-1, root);
VRANK2RANK(speer, vrank+1, root);
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
if(count == 0) return NBC_OK;
if (count == 0) {
return OMPI_SUCCESS;
}
numfrag = count * size/fragsize;
if ((count * size) % fragsize != 0) {
numfrag++;
}
numfrag = count*size/fragsize;
if((count*size)%fragsize != 0) numfrag++;
fragcount = count/numfrag;
/*if(!rank) printf("numfrag: %i, count: %i, size: %i, fragcount: %i\n", numfrag, count, size, fragcount);*/
for(fragnum = 0; fragnum < numfrag; fragnum++) {
buf = (char*)buffer+fragnum*fragcount*ext;
for (int fragnum = 0 ; fragnum < numfrag ; ++fragnum) {
buf = (char *) buffer + fragnum * fragcount * ext;
thiscount = fragcount;
if(fragnum == numfrag-1) {
if (fragnum == numfrag-1) {
/* last fragment may not be full */
thiscount = count-fragcount*fragnum;
thiscount = count - fragcount * fragnum;
}
/* root does not receive */
if(vrank != 0) {
res = NBC_Sched_recv(buf, false, thiscount, datatype, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (vrank != 0) {
res = NBC_Sched_recv (buf, false, thiscount, datatype, rpeer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
/* last rank does not send */
if(vrank != p-1) {
res = NBC_Sched_send(buf, false, thiscount, datatype, speer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (vrank != p-1) {
res = NBC_Sched_send (buf, false, thiscount, datatype, speer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* this barrier here seems awaward but isn't!!!! */
if(vrank == 0) res = NBC_Sched_barrier(schedule);
if (vrank == 0) {
res = NBC_Sched_barrier (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
}
}
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -15,54 +18,66 @@
int ompi_coll_libnbc_ibcast_inter(void *buffer, int count, MPI_Datatype datatype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, size, peer;
int res, size;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_size(datatype, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
handle->tmpbuf=NULL;
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
if(root != MPI_PROC_NULL) {
if (root != MPI_PROC_NULL) {
/* send to all others */
if(root == MPI_ROOT) {
if (root == MPI_ROOT) {
int remsize;
res = MPI_Comm_remote_size(comm, &remsize);
if(MPI_SUCCESS != res) { printf("MPI_Comm_remote_size() failed\n"); return res; }
remsize = ompi_comm_remote_size (comm);
for (peer=0;peer<remsize;peer++) {
for (int peer = 0 ; peer < remsize ; ++peer) {
/* send msg to peer */
res = NBC_Sched_send(buffer, false, count, datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (buffer, false, count, datatype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
} else {
/* recv msg from root */
res = NBC_Sched_recv(buffer, false, count, datatype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (buffer, false, count, datatype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -5,7 +5,7 @@
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -18,18 +18,19 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Scan_args_compare(NBC_Scan_args *a, NBC_Scan_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->recvbuf == b->recvbuf) &&
(a->count == b->count) &&
(a->datatype == b->datatype) &&
(a->op == b->op) ) {
return 0;
return 0;
}
if( a->sendbuf < b->sendbuf ) {
return -1;
}
return +1;
return 1;
}
#endif
@ -51,114 +52,162 @@ int ompi_coll_libnbc_iexscan(void* sendbuf, void* recvbuf, int count, MPI_Dataty
#endif
char inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if (res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
if (inplace && rank < p - 1)
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if (inplace && rank < p - 1) {
/* need more buffer space for the inplace case */
handle->tmpbuf = malloc(ext * count * 2);
else
} else {
handle->tmpbuf = malloc(ext * count);
}
if (handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
if (handle->tmpbuf == NULL) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
#ifdef NBC_CACHE_SCHEDULE
fprintf (stderr, "NBC_CACHE_SCHEDULE\n");
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.recvbuf=recvbuf;
search.count=count;
search.datatype=datatype;
search.op=op;
found = (NBC_Scan_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_EXSCAN], &search);
if (found == NULL) {
search.sendbuf = sendbuf;
search.recvbuf = recvbuf;
search.count = count;
search.datatype = datatype;
search.op = op;
found = (NBC_Scan_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_EXSCAN], &search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if (res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
if (rank != 0) {
if (inplace && rank < p - 1)
if (inplace && rank < p - 1) {
/* if sendbuf == recvbuf do not clobber the send buffer until it has been combined
* with the incoming data. */
res = NBC_Sched_recv((void *)(ext * count), true, count, datatype, rank-1, schedule);
else
res = NBC_Sched_recv(recvbuf, false, count, datatype, rank-1, schedule);
res = NBC_Sched_recv ((void *) (ext * count), true, count, datatype, rank-1, schedule, false);
} else {
res = NBC_Sched_recv (recvbuf, false, count, datatype, rank-1, schedule, false);
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (rank < p - 1) {
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* perform the reduce in my temporary buffer */
if (inplace)
res = NBC_Sched_op(0, true, sendbuf, false, (void *)(ext * count), true, count, datatype, op, schedule);
else
res = NBC_Sched_op(0, true, sendbuf, false, recvbuf, false, count, datatype, op, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( so barrier after */
if (inplace) {
res = NBC_Sched_op (0, true, sendbuf, false, (void *)(ext * count), true, count,
datatype, op, schedule, true);
} else {
res = NBC_Sched_op (0, true, sendbuf, false, recvbuf, false, count, datatype, op,
schedule, true);
}
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* send reduced data onward */
res = NBC_Sched_send(0, true, count, datatype, rank + 1, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (0, true, count, datatype, rank + 1, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (inplace)
if (inplace) {
/* copy the received data into the receive buffer */
NBC_Sched_copy ((void *)(ext * count), true, count, datatype, recvbuf, false, count, datatype, schedule);
res = NBC_Sched_copy ((void *)(ext * count), true, count, datatype, recvbuf,
false, count, datatype, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
}
} else if (p > 1) {
res = NBC_Sched_send(sendbuf, false, count, datatype, 1, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sendbuf, false, count, datatype, 1, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Scan_args*)malloc(sizeof(NBC_Alltoall_args));
args->sendbuf=sendbuf;
args->recvbuf=recvbuf;
args->count=count;
args->datatype=datatype;
args->op=op;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_EXSCAN], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_EXSCAN] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_EXSCAN], &handle->comminfo->NBC_Dict_size[NBC_EXSCAN]);
args = (NBC_Scan_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->recvbuf = recvbuf;
args->count = count;
args->datatype = datatype;
args->op = op;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_EXSCAN], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_EXSCAN] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_EXSCAN],
&libnbc_module->NBC_Dict_size[NBC_EXSCAN]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -9,6 +10,8 @@
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -18,180 +21,223 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Gather_args_compare(NBC_Gather_args *a, NBC_Gather_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->sendcount == b->sendcount) &&
(a->sendtype == b->sendtype) &&
(a->recvbuf == b->recvbuf) &&
(a->recvcount == b->recvcount) &&
(a->recvtype == b->recvtype) &&
(a->root == b->root) ) {
return 0;
(a->root == b->root)) {
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if( a->sendbuf < b->sendbuf ) {
return -1;
}
return +1;
}
return 1;
}
#endif
int ompi_coll_libnbc_igather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, int root, struct ompi_communicator_t *comm, ompi_request_t ** request,
int ompi_coll_libnbc_igather(void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i;
int rank, p, res;
MPI_Aint rcvext = 0;
NBC_Schedule *schedule;
char *rbuf, inplace;
#ifdef NBC_CACHE_SCHEDULE
NBC_Gather_args *args, *found, search;
#endif
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
if (rank == root) {
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent (recvtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
handle->tmpbuf = NULL;
if (inplace) {
sendcount = recvcount;
sendtype = recvtype;
sendcount = recvcount;
sendtype = recvtype;
} else if (rank == root) {
rbuf = ((char *)recvbuf) + (rank*recvcount*rcvext);
/* if I am the root - just copy the message (only without MPI_IN_PLACE) */
res = NBC_Copy(sendbuf, sendcount, sendtype, rbuf, recvcount, recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.sendcount=sendcount;
search.sendtype=sendtype;
search.recvbuf=recvbuf;
search.recvcount=recvcount;
search.recvtype=recvtype;
search.root=root;
found = (NBC_Gather_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_GATHER], &search);
if(found == NULL) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
NBC_Gather_args *args, *found, search;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* search schedule in communicator specific tree */
search.sendbuf = sendbuf;
search.sendcount = sendcount;
search.sendtype = sendtype;
search.recvbuf = recvbuf;
search.recvcount = recvcount;
search.recvtype = recvtype;
search.root = root;
found = (NBC_Gather_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_GATHER],
&search);
if (NULL == found) {
#endif
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* send to root */
if(rank != root) {
if (rank != root) {
/* send msg to root */
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else {
for(i=0;i<p;i++) {
rbuf = ((char *)recvbuf) + (i*recvcount*rcvext);
if(i != root) {
for (int i = 0 ; i < p ; ++i) {
rbuf = (char *)recvbuf + i * recvcount * rcvext;
if (i != root) {
/* root receives message to the right buffer */
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Gather_args*)malloc(sizeof(NBC_Gather_args));
args->sendbuf=sendbuf;
args->sendcount=sendcount;
args->sendtype=sendtype;
args->recvbuf=recvbuf;
args->recvcount=recvcount;
args->recvtype=recvtype;
args->root=root;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_GATHER], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_GATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_GATHER], &handle->comminfo->NBC_Dict_size[NBC_GATHER]);
args = (NBC_Gather_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->sendcount = sendcount;
args->sendtype = sendtype;
args->recvbuf = recvbuf;
args->recvcount = recvcount;
args->recvtype = recvtype;
args->root = root;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_GATHER], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_GATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_GATHER],
&libnbc_module->NBC_Dict_size[NBC_GATHER]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_igather_inter (void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf, int recvcount,
MPI_Datatype recvtype, int root, struct ompi_communicator_t *comm, ompi_request_t ** request,
int ompi_coll_libnbc_igather_inter (void* sendbuf, int sendcount, MPI_Datatype sendtype, void* recvbuf,
int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i, rsize;
int res, rsize;
MPI_Aint rcvext = 0;
NBC_Schedule *schedule;
char *rbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_remote_size (comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
if (root == MPI_ROOT) {
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
}
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* send to root */
if(root != MPI_ROOT && root != MPI_PROC_NULL) {
/* send msg to root */
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
} else if (MPI_ROOT == root) {
for (i = 0 ; i < rsize ; ++i) {
rbuf = ((char *)recvbuf) + (i * recvcount * rcvext);
/* root receives message to the right buffer */
res = NBC_Sched_recv(rbuf, false, recvcount, recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
/* send to root */
if (root != MPI_ROOT && root != MPI_PROC_NULL) {
/* send msg to root */
res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else if (MPI_ROOT == root) {
for (int i = 0 ; i < rsize ; ++i) {
rbuf = ((char *)recvbuf) + (i * recvcount * rcvext);
/* root receives message to the right buffer */
res = NBC_Sched_recv (rbuf, false, recvcount, recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
return NBC_OK;
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -9,6 +10,8 @@
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -24,118 +27,151 @@ int ompi_coll_libnbc_igatherv(void* sendbuf, int sendcount, MPI_Datatype sendtyp
void* recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype,
int root, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i;
int rank, p, res;
MPI_Aint rcvext = 0;
NBC_Schedule *schedule;
char *rbuf, inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
if (rank == root) {
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* send to root */
if(rank != root) {
if (rank != root) {
/* send msg to root */
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else {
for(i=0;i<p;i++) {
rbuf = ((char *)recvbuf) + (displs[i]*rcvext);
if(i == root) {
if(!inplace) {
for (int i = 0 ; i < p ; ++i) {
rbuf = (char *) recvbuf + displs[i] * rcvext;
if (i == root) {
if (!inplace) {
/* if I am the root - just copy the message */
res = NBC_Copy(sendbuf, sendcount, sendtype, rbuf, recvcounts[i], recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
res = NBC_Copy (sendbuf, sendcount, sendtype, rbuf, recvcounts[i], recvtype,
comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
} else {
/* root receives message to the right buffer */
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_igatherv_inter (void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int *recvcounts, int *displs, MPI_Datatype recvtype,
int root, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i, rsize;
int res, rsize;
MPI_Aint rcvext;
NBC_Schedule *schedule;
char *rbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_remote_size (comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
rsize = ompi_comm_size (comm);
if (MPI_ROOT == root) {
res = MPI_Type_extent(recvtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* send to root */
if (MPI_ROOT != root && MPI_PROC_NULL != root) {
/* send msg to root */
res = NBC_Sched_send(sendbuf, false, sendcount, sendtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sendbuf, false, sendcount, sendtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else if (MPI_ROOT == root) {
for (i = 0 ; i < rsize ; ++i) {
rbuf = ((char *)recvbuf) + (displs[i]*rcvext);
for (int i = 0 ; i < rsize ; ++i) {
rbuf = (char *) recvbuf + displs[i] * rcvext;
/* root receives message to the right buffer */
res = NBC_Sched_recv(rbuf, false, recvcounts[i], recvtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (rbuf, false, recvcounts[i], recvtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -18,7 +21,7 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Ineighbor_allgather_args_compare(NBC_Ineighbor_allgather_args *a, NBC_Ineighbor_allgather_args *b, void *param) {
if( (a->sbuf == b->sbuf) &&
if ((a->sbuf == b->sbuf) &&
(a->scount == b->scount) &&
(a->stype == b->stype) &&
(a->rbuf == b->rbuf) &&
@ -26,10 +29,12 @@ int NBC_Ineighbor_allgather_args_compare(NBC_Ineighbor_allgather_args *a, NBC_In
(a->rtype == b->rtype) ) {
return 0;
}
if( a->sbuf < b->sbuf ) {
return -1;
}
return +1;
return 1;
}
#endif
@ -37,129 +42,127 @@ int NBC_Ineighbor_allgather_args_compare(NBC_Ineighbor_allgather_args *a, NBC_In
int ompi_coll_libnbc_ineighbor_allgather(void *sbuf, int scount, MPI_Datatype stype, void *rbuf,
int rcount, MPI_Datatype rtype, struct ompi_communicator_t *comm,
ompi_request_t ** request, struct mca_coll_base_module_2_1_0_t *module) {
int rank, size, res, worldsize;
MPI_Aint sndext, rcvext;
int res, indegree, outdegree, *srcs, *dsts;
MPI_Aint rcvext;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
handle = *coll_req;
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(stype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
char inplace;
NBC_Schedule *schedule;
res = MPI_Type_extent (rtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
NBC_Ineighbor_allgather_args *args, *found, search;
#endif
NBC_IN_PLACE(sbuf, rbuf, inplace);
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sbuf=sbuf;
search.scount=scount;
search.stype=stype;
search.rbuf=rbuf;
search.rcount=rcount;
search.rtype=rtype;
found = (NBC_Ineighbor_allgather_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHER], &search);
if(found == NULL) {
search.sbuf = sbuf;
search.scount = scount;
search.stype = stype;
search.rbuf = rbuf;
search.rcount = rcount;
search.rtype = rtype;
found = (NBC_Ineighbor_allgather_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHER],
&search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
res = NBC_Comm_neighbors (comm, &srcs, &indegree, &dsts, &outdegree);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
{
int indegree, outdegree, weighted, *srcs, *dsts, i;
res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted);
if(res != NBC_OK) return res;
srcs = (int*)malloc(sizeof(int)*indegree);
dsts = (int*)malloc(sizeof(int)*outdegree);
res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED);
if(res != NBC_OK) return res;
if(inplace) { /* we need an extra buffer to be deadlock-free */
handle->tmpbuf = malloc(indegree*rcvext*rcount);
for(i = 0; i < indegree; i++) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv((char*)0+i*rcount*rcvext, true, rcount, rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* unpack from buffer */
for(i = 0; i < indegree; i++) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_copy((char*)0+i*rcount*rcvext, true, rcount, rtype, (char*)rbuf+i*rcount*rcvext, false, rcount, rtype, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
} else { /* non INPLACE case */
/* simply loop over neighbors and post send/recv operations */
for(i = 0; i < indegree; i++) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv((char*)rbuf+i*rcount*rcvext, false, rcount, rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
for (int i = 0 ; i < indegree ; ++i) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv ((char *) rbuf + i * rcount * rcvext, true, rcount, rtype, srcs[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
free (srcs);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
free (dsts);
return res;
}
for (int i = 0 ; i < outdegree ; ++i) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send ((char *) sbuf, false, scount, stype, dsts[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (dsts);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Ineighbor_allgather_args*)malloc(sizeof(NBC_Ineighbor_allgather_args));
args->sbuf=sbuf;
args->scount=scount;
args->stype=stype;
args->rbuf=rbuf;
args->rcount=rcount;
args->rtype=rtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHER], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHER], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHER]);
}
args = (NBC_Ineighbor_allgather_args *) malloc (sizeof (args));
if (NULL != args) {
args->sbuf = sbuf;
args->scount = scount;
args->stype = stype;
args->rbuf = rbuf;
args->rcount = rcount;
args->rtype = rtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHER], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHER],
&libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHER]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start(handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
OBJ_RELEASE(schedule);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -18,18 +21,20 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Ineighbor_allgatherv_args_compare(NBC_Ineighbor_allgatherv_args *a, NBC_Ineighbor_allgatherv_args *b, void *param) {
if( (a->sbuf == b->sbuf) &&
if ((a->sbuf == b->sbuf) &&
(a->scount == b->scount) &&
(a->stype == b->stype) &&
(a->rbuf == b->rbuf) &&
(a->rcount == b->rcount) &&
(a->rtype == b->rtype) ) {
return 0;
return 0;
}
if( a->sbuf < b->sbuf ) {
return -1;
}
return +1;
return 1;
}
#endif
@ -38,138 +43,128 @@ int ompi_coll_libnbc_ineighbor_allgatherv(void *sbuf, int scount, MPI_Datatype s
int *rcounts, int *displs, MPI_Datatype rtype,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, size, res, worldsize;
MPI_Aint sndext, rcvext;
int res, indegree, outdegree, *srcs, *dsts;
MPI_Aint rcvext;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
handle = *coll_req;
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(stype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
char inplace;
NBC_Schedule *schedule;
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
NBC_Ineighbor_allgatherv_args *args, *found, search;
#endif
NBC_IN_PLACE(sbuf, rbuf, inplace);
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sbuf=sbuf;
search.scount=scount;
search.stype=stype;
search.rbuf=rbuf;
search.rcount=rcount;
search.rtype=rtype;
found = (NBC_Ineighbor_allgatherv_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], &search);
if(found == NULL) {
search.sbuf = sbuf;
search.scount = scount;
search.stype = stype;
search.rbuf = rbuf;
search.rcount = rcount;
search.rtype = rtype;
found = (NBC_Ineighbor_allgatherv_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV],
&search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
res = NBC_Comm_neighbors(comm, &srcs, &indegree, &dsts, &outdegree);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
{
int indegree, outdegree, weighted, *srcs, *dsts, i;
res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted);
if(res != NBC_OK) return res;
srcs = (int*)malloc(sizeof(int)*indegree);
dsts = (int*)malloc(sizeof(int)*outdegree);
res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED);
if(res != NBC_OK) return res;
if(inplace) { /* we need an extra buffer to be deadlock-free */
int sumrcounts=0;
int offset=0;
for(i=0; i<indegree; ++i) sumrcounts += rcounts[i];
handle->tmpbuf = malloc(rcvext*sumrcounts);
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)0+offset, true, rcounts[i], rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
offset += rcounts[i]*rcvext;
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* unpack from buffer */
offset=0;
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_copy((char*)0+offset, true, rcounts[i], rtype, (char*)rbuf+displs[i]*rcvext, false, rcounts[i], rtype, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
offset += rcounts[i]*rcvext;
}
} else { /* non INPLACE case */
/* simply loop over neighbors and post send/recv operations */
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)rbuf+displs[i]*rcvext, false, rcounts[i], rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
/* simply loop over neighbors and post send/recv operations */
for (int i = 0 ; i < indegree ; ++i) {
if (srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv ((char *) rbuf + displs[i] * rcvext, false, rcounts[i], rtype, srcs[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
free (srcs);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
free (dsts);
OBJ_RELEASE(schedule);
return res;
}
for (int i = 0 ; i < outdegree ; ++i) {
if (dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send ((char *) sbuf, false, scount, stype, dsts[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (dsts);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Ineighbor_allgatherv_args*)malloc(sizeof(NBC_Ineighbor_allgatherv_args));
args->sbuf=sbuf;
args->scount=scount;
args->stype=stype;
args->rbuf=rbuf;
args->rcount=rcount;
args->rtype=rtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV]);
args = (NBC_Ineighbor_allgatherv_args *) malloc (sizeof (args));
if (NULL != args) {
args->sbuf = sbuf;
args->scount = scount;
args->stype = stype;
args->rbuf = rbuf;
args->rcount = rcount;
args->rtype = rtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if(++libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLGATHERV],
&libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLGATHERV]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
OBJ_RELEASE(schedule);
return OMPI_ERR_OUT_OF_RESOURCE;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -36,129 +39,133 @@ int NBC_Ineighbor_alltoall_args_compare(NBC_Ineighbor_alltoall_args *a, NBC_Inei
int ompi_coll_libnbc_ineighbor_alltoall(void *sbuf, int scount, MPI_Datatype stype, void *rbuf,
int rcount, MPI_Datatype rtype, struct ompi_communicator_t *comm,
ompi_request_t ** request, struct mca_coll_base_module_2_1_0_t *module) {
int rank, size, res, worldsize;
int res, indegree, outdegree, *srcs, *dsts;
MPI_Aint sndext, rcvext;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
handle = *coll_req;
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
NBC_Schedule *schedule;
res = MPI_Type_extent(stype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
char inplace;
NBC_Schedule *schedule;
#ifdef NBC_CACHE_SCHEDULE
NBC_Ineighbor_alltoall_args *args, *found, search;
#endif
NBC_IN_PLACE(sbuf, rbuf, inplace);
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sbuf=sbuf;
search.scount=scount;
search.stype=stype;
search.rbuf=rbuf;
search.rcount=rcount;
search.rtype=rtype;
found = (NBC_Ineighbor_alltoall_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALL], &search);
if(found == NULL) {
search.sbuf = sbuf;
search.scount = scount;
search.stype = stype;
search.rbuf = rbuf;
search.rcount = rcount;
search.rtype = rtype;
found = (NBC_Ineighbor_alltoall_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALL],
&search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
res = NBC_Comm_neighbors(comm, &srcs, &indegree, &dsts, &outdegree);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
{
int indegree, outdegree, weighted, *srcs, *dsts, i;
res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted);
if(res != NBC_OK) return res;
srcs = indegree ? (int*)malloc(sizeof(int)*indegree) : NULL;
dsts = outdegree ? (int*)malloc(sizeof(int)*outdegree) : NULL;
res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED);
if(res != NBC_OK) return res;
if(inplace) { /* we need an extra buffer to be deadlock-free */
handle->tmpbuf = malloc(indegree*rcvext*rcount);
for(i = 0; i < indegree; i++) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv((char*)0+i*rcount*rcvext, true, rcount, rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send((char*)sbuf+i*scount*sndext, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* unpack from buffer */
for(i = 0; i < indegree; i++) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_copy((char*)0+i*rcount*rcvext, true, rcount, rtype, (char*)rbuf+i*rcount*rcvext, false, rcount, rtype, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
} else { /* non INPLACE case */
/* simply loop over neighbors and post send/recv operations */
for(i = 0; i < indegree; i++) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv((char*)rbuf+i*rcount*rcvext, false, rcount, rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send((char*)sbuf+i*scount*sndext, false, scount, stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
for (int i = 0 ; i < indegree ; ++i) {
if (MPI_PROC_NULL != srcs[i]) {
res = NBC_Sched_recv ((char *) rbuf + i * rcount * rcvext, true, rcount, rtype, srcs[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
free (srcs);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
free (dsts);
return res;
}
for (int i = 0 ; i < outdegree ; ++i) {
if (MPI_PROC_NULL != dsts[i]) {
res = NBC_Sched_send ((char *) sbuf + i * scount * sndext, false, scount, stype, dsts[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (dsts);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Ineighbor_alltoall_args*)malloc(sizeof(NBC_Ineighbor_alltoall_args));
args->sbuf=sbuf;
args->scount=scount;
args->stype=stype;
args->rbuf=rbuf;
args->rcount=rcount;
args->rtype=rtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALL], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALL] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALL], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALL]);
args = (NBC_Ineighbor_alltoall_args *) malloc (sizeof (args));
if (NULL != args) {
args->sbuf = sbuf;
args->scount = scount;
args->stype = stype;
args->rbuf = rbuf;
args->rcount = rcount;
args->rtype = rtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALL], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALL] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALL],
&libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALL]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -18,18 +21,20 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Ineighbor_alltoallv_args_compare(NBC_Ineighbor_alltoallv_args *a, NBC_Ineighbor_alltoallv_args *b, void *param) {
if( (a->sbuf == b->sbuf) &&
if ((a->sbuf == b->sbuf) &&
(a->scount == b->scount) &&
(a->stype == b->stype) &&
(a->rbuf == b->rbuf) &&
(a->rcount == b->rcount) &&
(a->rtype == b->rtype) ) {
return 0;
return 0;
}
if( a->sbuf < b->sbuf ) {
if (a->sbuf < b->sbuf) {
return -1;
}
return +1;
return 1;
}
#endif
@ -38,138 +43,134 @@ int ompi_coll_libnbc_ineighbor_alltoallv(void *sbuf, int *scounts, int *sdispls,
void *rbuf, int *rcounts, int *rdispls, MPI_Datatype rtype,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, size, res, worldsize;
int res, indegree, outdegree, *srcs, *dsts;
MPI_Aint sndext, rcvext;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
handle = *coll_req;
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(stype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent(rtype, &rcvext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
char inplace;
NBC_Schedule *schedule;
res = MPI_Type_extent (stype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_extent (rtype, &rcvext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
NBC_Ineighbor_alltoallv_args *args, *found, search;
#endif
NBC_IN_PLACE(sbuf, rbuf, inplace);
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sbuf=sbuf;
search.scount=scount;
search.stype=stype;
search.rbuf=rbuf;
search.rcount=rcount;
search.rtype=rtype;
found = (NBC_Ineighbor_alltoallv_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV], &search);
if(found == NULL) {
search.sbuf = sbuf;
search.scount = scount;
search.stype = stype;
search.rbuf = rbuf;
search.rcount = rcount;
search.rtype = rtype;
found = (NBC_Ineighbor_alltoallv_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV],
&search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
res = NBC_Comm_neighbors (comm, &srcs, &indegree, &dsts, &outdegree);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
{
int indegree, outdegree, weighted, *srcs, *dsts, i;
res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted);
if(res != NBC_OK) return res;
srcs = (int*)malloc(sizeof(int)*indegree);
dsts = (int*)malloc(sizeof(int)*outdegree);
res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED);
if(res != NBC_OK) return res;
if(inplace) { /* we need an extra buffer to be deadlock-free */
int sumrcounts=0;
int offset=0;
for(i=0; i<indegree; ++i) sumrcounts += rcounts[i];
handle->tmpbuf = malloc(rcvext*sumrcounts);
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)0+offset, true, rcounts[i], rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
offset += rcounts[i]*rcvext;
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf+sdispls[i]*sndext, false, scounts[i], stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* unpack from buffer */
offset=0;
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_copy((char*)0+offset, true, rcounts[i], rtype, (char*)rbuf+rdispls[i]*rcvext, false, rcounts[i], rtype, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
offset += rcounts[i]*rcvext;
}
} else { /* non INPLACE case */
/* simply loop over neighbors and post send/recv operations */
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)rbuf+rdispls[i]*rcvext, false, rcounts[i], rtype, srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf+sdispls[i]*sndext, false, scounts[i], stype, dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
/* simply loop over neighbors and post send/recv operations */
for (int i = 0 ; i < indegree ; ++i) {
if (srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv ((char *) rbuf + rdispls[i] * rcvext, false, rcounts[i], rtype, srcs[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
free (srcs);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
free (dsts);
return res;
}
for (int i = 0 ; i < outdegree ; ++i) {
if (dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send ((char *) sbuf + sdispls[i] * sndext, false, scounts[i], stype, dsts[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (dsts);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Ineighbor_alltoallv_args*)malloc(sizeof(NBC_Ineighbor_alltoallv_args));
args->sbuf=sbuf;
args->scount=scount;
args->stype=stype;
args->rbuf=rbuf;
args->rcount=rcount;
args->rtype=rtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLV] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLV]);
args = (NBC_Ineighbor_alltoallv_args *) malloc (sizeof (args));
if (NULL != args) {
args->sbuf = sbuf;
args->scount = scount;
args->stype = stype;
args->rbuf = rbuf;
args->rcount = rcount;
args->rtype = rtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLV] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLV],
&libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLV]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -18,18 +21,20 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Ineighbor_alltoallw_args_compare(NBC_Ineighbor_alltoallw_args *a, NBC_Ineighbor_alltoallw_args *b, void *param) {
if( (a->sbuf == b->sbuf) &&
if ((a->sbuf == b->sbuf) &&
(a->scount == b->scount) &&
(a->stype == b->stype) &&
(a->rbuf == b->rbuf) &&
(a->rcount == b->rcount) &&
(a->rtype == b->rtype) ) {
return 0;
(a->rtype == b->rtype)) {
return 0;
}
if( a->sbuf < b->sbuf ) {
if (a->sbuf < b->sbuf) {
return -1;
}
return +1;
return 1;
}
#endif
@ -37,137 +42,119 @@ int ompi_coll_libnbc_ineighbor_alltoallw(void *sbuf, int *scounts, MPI_Aint *sdi
void *rbuf, int *rcounts, MPI_Aint *rdisps, MPI_Datatype *rtypes,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, size, res, worldsize;
MPI_Aint *sndexts, *rcvexts;
int res, indegree, outdegree, *srcs, *dsts;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
handle = *coll_req;
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
char inplace;
NBC_Schedule *schedule;
#ifdef NBC_CACHE_SCHEDULE
NBC_Ineighbor_alltoallw_args *args, *found, search;
#endif
NBC_IN_PLACE(sbuf, rbuf, inplace);
handle->tmpbuf=NULL;
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sbuf=sbuf;
search.scount=scount;
search.stype=stype;
search.rbuf=rbuf;
search.rcount=rcount;
search.rtype=rtype;
found = (NBC_Ineighbor_alltoallw_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], &search);
search.sbuf = sbuf;
search.scount = scount;
search.stype = stype;
search.rbuf = rbuf;
search.rcount = rcount;
search.rtype = rtype;
found = (NBC_Ineighbor_alltoallw_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW],
&search);
if(found == NULL) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create, res = %i\n", res); return res; }
res = NBC_Comm_neighbors (comm, &srcs, &indegree, &dsts, &outdegree);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
{
int indegree, outdegree, weighted, *srcs, *dsts, i;
res = NBC_Comm_neighbors_count(comm, &indegree, &outdegree, &weighted);
if(res != NBC_OK) return res;
srcs = (int*)malloc(sizeof(int)*indegree);
dsts = (int*)malloc(sizeof(int)*outdegree);
sndexts = (MPI_Aint*)malloc(sizeof(MPI_Aint)*outdegree);
for(i=0; i<outdegree; ++i) {
res = MPI_Type_extent(stypes[i], &sndexts[i]);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
}
rcvexts = (MPI_Aint*)malloc(sizeof(MPI_Aint)*indegree);
for(i=0; i<indegree; ++i) {
res = MPI_Type_extent(rtypes[i], &rcvexts[i]);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
}
res = NBC_Comm_neighbors(comm, indegree, srcs, MPI_UNWEIGHTED, outdegree, dsts, MPI_UNWEIGHTED);
if(res != NBC_OK) return res;
if(inplace) { /* we need an extra buffer to be deadlock-free */
int sumrbytes=0;
for(i=0; i<indegree; ++i) sumrbytes += rcounts[i]*rcvexts[i];
handle->tmpbuf = malloc(sumrbytes);
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)0+rdisps[i], true, rcounts[i], rtypes[i], srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf+sdisps[i], false, scounts[i], stypes[i], dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
}
/* unpack from buffer */
for(i = 0; i < indegree; i++) {
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_copy((char*)0+rdisps[i], true, rcounts[i], rtypes[i], (char*)rbuf+rdisps[i], false, rcounts[i], rtypes[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
}
} else { /* non INPLACE case */
/* simply loop over neighbors and post send/recv operations */
for(i = 0; i < indegree; i++) {
if(srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv((char*)rbuf+rdisps[i], false, rcounts[i], rtypes[i], srcs[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
}
for(i = 0; i < outdegree; i++) {
if(dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send((char*)sbuf+sdisps[i], false, scounts[i], stypes[i], dsts[i], schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
}
/* simply loop over neighbors and post send/recv operations */
for (int i = 0 ; i < indegree ; ++i) {
if (srcs[i] != MPI_PROC_NULL) {
res = NBC_Sched_recv ((char *) rbuf + rdisps[i], false, rcounts[i], rtypes[i], srcs[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (srcs);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
for (int i = 0 ; i < outdegree ; ++i) {
if (dsts[i] != MPI_PROC_NULL) {
res = NBC_Sched_send ((char *) sbuf + sdisps[i], false, scounts[i], stypes[i], dsts[i], schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
break;
}
}
}
free (dsts);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Ineighbor_alltoallw_args*)malloc(sizeof(NBC_Ineighbor_alltoallw_args));
args->sbuf=sbuf;
args->scount=scount;
args->stype=stype;
args->rbuf=rbuf;
args->rcount=rcount;
args->rtype=rtype;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], &handle->comminfo->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW]);
}
args = (NBC_Ineighbor_alltoallw_args *) malloc (sizeof (args));
if (NULL != args) {
args->sbuf = sbuf;
args->scount = scount;
args->stype = stype;
args->rbuf = rbuf;
args->rcount = rcount;
args->rtype = rtype;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_NEIGHBOR_ALLTOALLW],
&libnbc_module->NBC_Dict_size[NBC_NEIGHBOR_ALLTOALLW]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start(handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -11,6 +12,8 @@
* Copyright (c) 2014 NVIDIA Corporation. All rights reserved.
* Copyright (c) 2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
*/
#ifndef __NBC_INTERNAL_H__
@ -30,6 +33,7 @@
#include "ompi/include/ompi/constants.h"
#include "ompi/request/request.h"
#include "ompi/datatype/ompi_datatype.h"
#include "ompi/communicator/communicator.h"
#include <stdlib.h>
#include <stdio.h>
@ -82,66 +86,74 @@ typedef enum {
/* the send argument struct */
typedef struct {
void *buf;
char tmpbuf;
NBC_Fn_type type;
int count;
void *buf;
MPI_Datatype datatype;
int dest;
char tmpbuf;
} NBC_Args_send;
/* the receive argument struct */
typedef struct {
void *buf;
char tmpbuf;
NBC_Fn_type type;
int count;
void *buf;
MPI_Datatype datatype;
char tmpbuf;
int source;
} NBC_Args_recv;
/* the operation argument struct */
typedef struct {
void *buf1;
NBC_Fn_type type;
char tmpbuf1;
void *buf2;
char tmpbuf2;
void *buf3;
char tmpbuf3;
int count;
void *buf1;
void *buf2;
void *buf3;
MPI_Op op;
MPI_Datatype datatype;
int count;
} NBC_Args_op;
/* the copy argument struct */
typedef struct {
void *src;
char tmpsrc;
NBC_Fn_type type;
int srccount;
MPI_Datatype srctype;
void *src;
void *tgt;
char tmptgt;
int tgtcount;
MPI_Datatype srctype;
MPI_Datatype tgttype;
int tgtcount;
char tmpsrc;
char tmptgt;
} NBC_Args_copy;
/* unpack operation arguments */
typedef struct {
void *inbuf;
char tmpinbuf;
NBC_Fn_type type;
int count;
MPI_Datatype datatype;
void *inbuf;
void *outbuf;
MPI_Datatype datatype;
char tmpinbuf;
char tmpoutbuf;
} NBC_Args_unpack;
/* internal function prototypes */
int NBC_Sched_create(NBC_Schedule* schedule);
int NBC_Sched_send(void* buf, char tmpbuf, int count, MPI_Datatype datatype, int dest, NBC_Schedule *schedule);
int NBC_Sched_recv(void* buf, char tmpbuf, int count, MPI_Datatype datatype, int source, NBC_Schedule *schedule);
int NBC_Sched_op(void* buf3, char tmpbuf3, void* buf1, char tmpbuf1, void* buf2, char tmpbuf2, int count, MPI_Datatype datatype, MPI_Op op, NBC_Schedule *schedule);
int NBC_Sched_copy(void *src, char tmpsrc, int srccount, MPI_Datatype srctype, void *tgt, char tmptgt, int tgtcount, MPI_Datatype tgttype, NBC_Schedule *schedule);
int NBC_Sched_unpack(void *inbuf, char tmpinbuf, int count, MPI_Datatype datatype, void *outbuf, char tmpoutbuf, NBC_Schedule *schedule);
int NBC_Sched_barrier(NBC_Schedule *schedule);
int NBC_Sched_commit(NBC_Schedule *schedule);
int NBC_Sched_send (void* buf, char tmpbuf, int count, MPI_Datatype datatype, int dest, NBC_Schedule *schedule, bool barrier);
int NBC_Sched_recv (void* buf, char tmpbuf, int count, MPI_Datatype datatype, int source, NBC_Schedule *schedule, bool barrier);
int NBC_Sched_op (void* buf3, char tmpbuf3, void* buf1, char tmpbuf1, void* buf2, char tmpbuf2, int count, MPI_Datatype datatype,
MPI_Op op, NBC_Schedule *schedule, bool barrier);
int NBC_Sched_copy (void *src, char tmpsrc, int srccount, MPI_Datatype srctype, void *tgt, char tmptgt, int tgtcount,
MPI_Datatype tgttype, NBC_Schedule *schedule, bool barrier);
int NBC_Sched_unpack (void *inbuf, char tmpinbuf, int count, MPI_Datatype datatype, void *outbuf, char tmpoutbuf,
NBC_Schedule *schedule, bool barrier);
int NBC_Sched_barrier (NBC_Schedule *schedule);
int NBC_Sched_commit (NBC_Schedule *schedule);
#ifdef NBC_CACHE_SCHEDULE
/* this is a dummy structure which is used to get the schedule out of
@ -247,12 +259,21 @@ void NBC_SchedCache_args_delete_key_dummy(void *k);
int NBC_Start(NBC_Handle *handle, NBC_Schedule *schedule);
int NBC_Init_handle(struct ompi_communicator_t *comm, ompi_coll_libnbc_request_t **request, ompi_coll_libnbc_module_t *module);
void NBC_Return_handle(ompi_coll_libnbc_request_t *request);
static inline int NBC_Type_intrinsic(MPI_Datatype type);
static inline int NBC_Copy(void *src, int srccount, MPI_Datatype srctype, void *tgt, int tgtcount, MPI_Datatype tgttype, MPI_Comm comm);
int NBC_Create_fortran_handle(int *fhandle, NBC_Handle **handle);
/* some macros */
static inline void NBC_Error (char *format, ...) {
va_list args;
va_start (args, format);
vfprintf (stderr, format, args);
fprintf (stderr, "\n");
va_end (args);
}
/* a schedule has the following format:
* [schedule] ::= [size][round-schedule][delimiter][round-schedule][delimiter]...[end]
* [size] ::= size of the schedule (int)
@ -277,83 +298,68 @@ int NBC_Create_fortran_handle(int *fhandle, NBC_Handle **handle);
* schedule. A round has the format:
* [num]{[type][type-args]}
* e.g. [(int)2][(NBC_Fn_type)SEND][(NBC_Args_send)SEND-ARGS][(NBC_Fn_type)RECV][(NBC_Args_recv)RECV-ARGS] */
#define NBC_GET_ROUND_SIZE(schedule, size) \
{ \
int num; \
char *p = (char*) schedule; \
NBC_Fn_type type; \
int i; \
\
NBC_GET_BYTES(p,num); \
/*NBC_DEBUG(10, "GET_ROUND_SIZE got %i elements\n", num); */\
for (i=0; i<num; i++) { \
NBC_GET_BYTES(p,type); \
switch(type) { \
case SEND: \
/*printf("found a SEND at offset %li\n", (long)p-(long)schedule); */\
p += sizeof(NBC_Args_send); \
break; \
case RECV: \
/*printf("found a RECV at offset %li\n", (long)p-(long)schedule); */\
p += sizeof(NBC_Args_recv); \
break; \
case OP: \
/*printf("found a OP at offset %li\n", (long)p-(long)schedule); */\
p += sizeof(NBC_Args_op); \
break; \
case COPY: \
/*printf("found a COPY at offset %li\n", (long)p-(long)schedule); */\
p += sizeof(NBC_Args_copy); \
break; \
case UNPACK: \
/*printf("found a UNPACK at offset %li\n", (long)p-(long)schedule); */\
p += sizeof(NBC_Args_unpack); \
break; \
default: \
printf("NBC_GET_ROUND_SIZE: bad type %i at offset %li\n", type, (long)p-sizeof(type)-(long)schedule); \
return NBC_BAD_SCHED; \
} \
} \
size = (long)p-(long)schedule; \
}
static inline void nbc_get_round_size (char *p, unsigned long *size) {
NBC_Fn_type type;
unsigned long offset = 0;
int num;
NBC_GET_BYTES(p,num);
/*NBC_DEBUG(10, "GET_ROUND_SIZE got %i elements\n", num); */
for (int i = 0 ; i < num ; ++i) {
memcpy (&type, p + offset, sizeof (type));
switch(type) {
case SEND:
/*printf("found a SEND at offset %li\n", (long)p-(long)schedule); */
offset += sizeof(NBC_Args_send);
break;
case RECV:
/*printf("found a RECV at offset %li\n", (long)p-(long)schedule); */
offset += sizeof(NBC_Args_recv);
break;
case OP:
/*printf("found a OP at offset %li\n", (long)p-(long)schedule); */
offset += sizeof(NBC_Args_op); \
break;
case COPY:
/*printf("found a COPY at offset %li\n", (long)p-(long)schedule); */
offset += sizeof(NBC_Args_copy);
break;
case UNPACK:
/*printf("found a UNPACK at offset %li\n", (long)p-(long)schedule); */
offset += sizeof(NBC_Args_unpack);
break;
default:
NBC_Error("NBC_GET_ROUND_SIZE: bad type %i at offset %li", type, offset);
return;
}
}
*size = offset + sizeof (int);
}
/* returns the size of a schedule in bytes */
#define NBC_GET_SIZE(schedule, size) \
{ \
size=*(int*)schedule; \
static inline int nbc_schedule_get_size (NBC_Schedule *schedule) {
return schedule->size;
}
/* increase the size of a schedule by size bytes */
#define NBC_INC_SIZE(schedule, size) \
{ \
*(int*)schedule+=size; \
static inline void nbc_schedule_inc_size (NBC_Schedule *schedule, int size) {
schedule->size += size;
}
/* increments the number of operations in the last round */
#define NBC_INC_NUM_ROUND(schedule) \
{ \
int total_size, num_last_round; \
long round_size; \
char *ptr, *lastround; \
\
NBC_GET_SIZE(schedule, total_size); \
\
/* ptr begins at first round (first int is overall size) */ \
ptr = (char*)schedule+sizeof(int); \
lastround = ptr; \
while ((long)ptr-(long)schedule < total_size) { \
NBC_GET_ROUND_SIZE(ptr, round_size); \
/*printf("got round_size %i\n", round_size);*/ \
lastround = ptr; \
ptr += round_size; \
ptr += sizeof(char); /* barrier delimiter */ \
/*printf("(long)ptr-(long)schedule=%li, total_size=%i\n", (long)ptr-(long)schedule, total_size); */\
} \
/*printf("lastround count is at offset: %li\n", (long)lastround-(long)schedule);*/ \
/* increment the count in the last round of the schedule */ \
memcpy(&num_last_round, lastround, sizeof(int)); \
num_last_round++; \
memcpy(lastround, &num_last_round, sizeof(int)); \
static inline void nbc_schedule_inc_round (NBC_Schedule *schedule) {
int last_round_num;
char *lastround;
lastround = schedule->data + schedule->current_round_offset;
/* increment the count in the last round of the schedule (memcpy is used
* to protect against unaligned access) */
memcpy (&last_round_num, lastround, sizeof (last_round_num));
++last_round_num;
memcpy (lastround, &last_round_num, sizeof (last_round_num));
}
/* NBC_PRINT_ROUND prints a round in a schedule. A round has the format:
@ -430,15 +436,6 @@ int NBC_Create_fortran_handle(int *fhandle, NBC_Handle **handle);
} \
}
#define NBC_CHECK_NULL(ptr) \
{ \
if(ptr == NULL) { \
printf("realloc error :-(\n"); \
} \
}
/*
#define NBC_DEBUG(level, ...) {}
*/
@ -498,27 +495,48 @@ static inline int NBC_Copy(void *src, int srccount, MPI_Datatype srctype, void *
/* if we have the same types and they are contiguous (intrinsic
* types are contiguous), we can just use a single memcpy */
res = ompi_datatype_get_extent(srctype, &lb, &ext);
if (OMPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (OMPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
memcpy(tgt, src, srccount*ext);
} else {
/* we have to pack and unpack */
res = MPI_Pack_size(srccount, srctype, comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack_size() (%i:%i)\n", res, size); return (MPI_SUCCESS == res) ? MPI_ERR_SIZE : res; }
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Pack_size() (%i:%i)", res, size);
return res;
}
if (0 == size) {
return NBC_OK;
return OMPI_SUCCESS;
}
packbuf = malloc(size);
if (NULL == packbuf) { printf("Error in malloc()\n"); return res; }
if (NULL == packbuf) {
NBC_Error("Error in malloc()");
return res;
}
pos=0;
res = MPI_Pack(src, srccount, srctype, packbuf, size, &pos, comm);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Pack() (%i)", res);
free (packbuf);
return res;
}
pos=0;
res = MPI_Unpack(packbuf, size, &pos, tgt, tgtcount, tgttype, comm);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Unpack() (%i)\n", res); return res; }
free(packbuf);
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Unpack() (%i)", res);
return res;
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
static inline int NBC_Unpack(void *src, int srccount, MPI_Datatype srctype, void *tgt, MPI_Comm comm) {
@ -533,19 +551,29 @@ static inline int NBC_Unpack(void *src, int srccount, MPI_Datatype srctype, void
/* if we have the same types and they are contiguous (intrinsic
* types are contiguous), we can just use a single memcpy */
res = ompi_datatype_get_extent (srctype, &lb, &ext);
if (OMPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (OMPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
memcpy(tgt, src, srccount * ext);
} else {
/* we have to unpack */
res = MPI_Pack_size(srccount, srctype, comm, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Pack_size() (%i)\n", res); return res; }
pos=0;
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Pack_size() (%i)", res);
return res;
}
pos = 0;
res = MPI_Unpack(src, size, &pos, tgt, srccount, srctype, comm);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Unpack() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Unpack() (%i)", res);
return res;
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
/* deletes elements from dict until low watermark is reached */
@ -576,8 +604,8 @@ static inline void NBC_SchedCache_dictwipe(hb_tree *dict, int *size) {
} \
}
int NBC_Comm_neighbors_count(MPI_Comm comm, int *indegree, int *outdegree, int *weighted);
int NBC_Comm_neighbors(MPI_Comm comm, int maxindegree, int sources[], int sourceweights[], int maxoutdegree, int destinations[], int destweights[]);
int NBC_Comm_neighbors_count (ompi_communicator_t *comm, int *indegree, int *outdegree);
int NBC_Comm_neighbors (ompi_communicator_t *comm, int **sources, int *source_count, int **destinations, int *dest_count);
#ifdef __cplusplus
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -14,26 +15,31 @@
*/
#include "nbc_internal.h"
static inline int red_sched_binomial(int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, void *redbuf, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int red_sched_chain(int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle, int fragsize);
static inline int red_sched_binomial (int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, void *redbuf, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int red_sched_chain (int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle, int fragsize);
static inline int red_sched_linear(int rank, int rsize, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle);
static inline int red_sched_linear (int rank, int rsize, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle);
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Reduce_args_compare(NBC_Reduce_args *a, NBC_Reduce_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->recvbuf == b->recvbuf) &&
(a->count == b->count) &&
(a->datatype == b->datatype) &&
(a->op == b->op) &&
(a->root == b->root) ) {
return 0;
(a->root == b->root)) {
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if (a->sendbuf < b->sendbuf) {
return -1;
}
return +1;
return 1;
}
#endif
@ -45,68 +51,86 @@ int ompi_coll_libnbc_ireduce(void* sendbuf, void* recvbuf, int count, MPI_Dataty
MPI_Aint ext;
NBC_Schedule *schedule;
char *redbuf=NULL, inplace;
#ifdef NBC_CACHE_SCHEDULE
NBC_Reduce_args *args, *found, search;
#endif
enum { NBC_RED_BINOMIAL, NBC_RED_CHAIN } alg;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = MPI_Type_size(datatype, &size);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_size() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_size() (%i)", res);
return res;
}
/* only one node -> copy data */
if((p == 1) && !inplace) {
res = NBC_Copy(sendbuf, count, datatype, recvbuf, count, datatype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
if ((p == 1) && !inplace) {
res = NBC_Copy (sendbuf, count, datatype, recvbuf, count, datatype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
*request = &ompi_request_empty;
return OMPI_SUCCESS;
}
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* algorithm selection */
if(p > 4 || size*count < 65536) {
if (p > 4 || size * count < 65536) {
alg = NBC_RED_BINOMIAL;
if(rank == root) {
/* root reduces in receivebuffer */
handle->tmpbuf = malloc(ext*count);
handle->tmpbuf = malloc (ext * count);
} else {
/* recvbuf may not be valid on non-root nodes */
handle->tmpbuf = malloc(ext*count*2);
redbuf = ((char*)handle->tmpbuf)+(ext*count);
handle->tmpbuf = malloc (ext * count * 2);
redbuf = (char*) handle->tmpbuf + ext * count;
}
} else {
handle->tmpbuf = malloc(ext*count);
handle->tmpbuf = malloc (ext * count);
alg = NBC_RED_CHAIN;
segsize = 16384/2;
}
if (NULL == handle->tmpbuf) { printf("Error in malloc() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.recvbuf=recvbuf;
search.count=count;
search.datatype=datatype;
search.op=op;
search.root=root;
found = (NBC_Reduce_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_REDUCE], &search);
if(found == NULL) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
NBC_Reduce_args *args, *found, search;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* search schedule in communicator specific tree */
search.sendbuf = sendbuf;
search.recvbuf = recvbuf;
search.count = count;
search.datatype = datatype;
search.op = op;
search.root = root;
found = (NBC_Reduce_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_REDUCE], &search);
if (NULL == found) {
#endif
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
switch(alg) {
case NBC_RED_BINOMIAL:
@ -116,37 +140,59 @@ int ompi_coll_libnbc_ireduce(void* sendbuf, void* recvbuf, int count, MPI_Dataty
res = red_sched_chain(rank, p, root, sendbuf, recvbuf, count, datatype, op, ext, size, schedule, handle, segsize);
break;
}
if (NBC_OK != res) { printf("Error in Schedule creation() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Reduce_args*)malloc(sizeof(NBC_Alltoall_args));
args->sendbuf=sendbuf;
args->recvbuf=recvbuf;
args->count=count;
args->datatype=datatype;
args->op=op;
args->root=root;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_REDUCE], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for Reduce */
if(++handle->comminfo->NBC_Dict_size[NBC_REDUCE] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_REDUCE], &handle->comminfo->NBC_Dict_size[NBC_REDUCE]);
args = (NBC_Reduce_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->recvbuf = recvbuf;
args->count = count;
args->datatype = datatype;
args->op = op;
args->root = root;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_REDUCE], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for Reduce */
if (++libnbc_module->NBC_Dict_size[NBC_REDUCE] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_REDUCE],
&libnbc_module->NBC_Dict_size[NBC_REDUCE]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_ireduce_inter(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
@ -156,40 +202,56 @@ int ompi_coll_libnbc_ireduce_inter(void* sendbuf, void* recvbuf, int count, MPI_
NBC_Schedule *schedule;
MPI_Aint ext;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
rank = ompi_comm_rank (comm);
rsize = ompi_comm_remote_size (comm);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent (datatype, &ext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
handle->tmpbuf = malloc(ext*count);
if (NULL == handle->tmpbuf) { printf("Error in malloc() (%i)\n", res); return res; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc() (%i)\n", res); return res; }
handle->tmpbuf = malloc (ext * count);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = red_sched_linear (rank, rsize, root, sendbuf, recvbuf, count, datatype, op, schedule, handle);
if (NBC_OK != res) { printf("Error in Schedule creation() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}
@ -222,156 +284,180 @@ int ompi_coll_libnbc_ireduce_inter(void* sendbuf, void* recvbuf, int count, MPI_
if (vrank == 0) rank = root; \
if (vrank == root) rank = 0; \
}
static inline int red_sched_binomial(int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, void *redbuf, NBC_Schedule *schedule, NBC_Handle *handle) {
int firstred, vrank, vpeer, peer, res, maxr, r;
static inline int red_sched_binomial (int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, void *redbuf, NBC_Schedule *schedule, NBC_Handle *handle) {
int vrank, vpeer, peer, res, maxr;
RANK2VRANK(rank, vrank, root);
maxr = (int)ceil((log((double)p)/LOG2));
firstred = 1;
for(r=1; r<=maxr; r++) {
if((vrank % (1<<r)) == 0) {
for (int r = 1, firstred = 1 ; r <= maxr ; ++r) {
if ((vrank % (1 << r)) == 0) {
/* we have to receive this round */
vpeer = vrank + (1<<(r-1));
vpeer = vrank + (1 << (r - 1));
VRANK2RANK(peer, vpeer, root)
if(peer<p) {
res = NBC_Sched_recv(0, true, count, datatype, peer, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
if (peer < p) {
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_recv (0, true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* perform the reduce in my local buffer */
if(firstred) {
if(rank == root) {
/* this cannot be done until handle->tmpbuf is unused :-( so barrier after the op */
if (firstred) {
if (rank == root) {
/* root is the only one who reduces in the receivebuffer
* take data from sendbuf in first round - save copy */
res = NBC_Sched_op(recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule, true);
} else {
/* all others may not have a receive buffer
* take data from sendbuf in first round - save copy */
res = NBC_Sched_op((char *)redbuf-(unsigned long)handle->tmpbuf, true, sendbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op ((char *) redbuf - (intptr_t) handle->tmpbuf, true, sendbuf, false, 0, true, count,
datatype, op, schedule, true);
}
firstred = 0;
} else {
if(rank == root) {
/* root is the only one who reduces in the receivebuffer */
res = NBC_Sched_op(recvbuf, false, recvbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (recvbuf, false, recvbuf, false, 0, true, count, datatype, op, schedule, true);
} else {
/* all others may not have a receive buffer */
res = NBC_Sched_op((char *)redbuf-(unsigned long)handle->tmpbuf, true, (char *)redbuf-(unsigned long)handle->tmpbuf, true, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op ((char *) redbuf - (intptr_t) handle->tmpbuf, true, (char *) redbuf - (intptr_t) handle->tmpbuf,
true, 0, true, count, datatype, op, schedule, true);
}
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
} else {
/* we have to send this round */
vpeer = vrank - (1<<(r-1));
vpeer = vrank - (1 << (r - 1));
VRANK2RANK(peer, vpeer, root)
if(firstred) {
if (firstred) {
/* we did not reduce anything */
res = NBC_Sched_send(sendbuf, false, count, datatype, peer, schedule);
res = NBC_Sched_send (sendbuf, false, count, datatype, peer, schedule, false);
} else {
/* we have to use the redbuf the root (which works in receivebuf) is never sending .. */
res = NBC_Sched_send((char *)redbuf-(unsigned long)handle->tmpbuf, true, count, datatype, peer, schedule);
res = NBC_Sched_send ((char *) redbuf - (intptr_t) handle->tmpbuf, true, count, datatype, peer, schedule,
false);
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* leave the game */
break;
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
/* chain send ... */
static inline int red_sched_chain(int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle, int fragsize) {
int res, vrank, rpeer, speer, numfrag, fragnum, fragcount, thiscount;
static inline int red_sched_chain (int rank, int p, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, int ext, int size, NBC_Schedule *schedule, NBC_Handle *handle, int fragsize) {
int res, vrank, rpeer, speer, numfrag, fragcount, thiscount;
long offset;
RANK2VRANK(rank, vrank, root);
VRANK2RANK(rpeer, vrank+1, root);
VRANK2RANK(speer, vrank-1, root);
if(count == 0) return NBC_OK;
if (0 == count) {
return OMPI_SUCCESS;
}
numfrag = count*size/fragsize;
if((count*size)%fragsize != 0) numfrag++;
fragcount = count/numfrag;
/*printf("numfrag: %i, count: %i, size: %i, fragcount: %i\n", numfrag, count, size, fragcount);*/
numfrag = count * size / fragsize;
if ((count * size) % fragsize != 0) {
numfrag++;
}
for(fragnum = 0; fragnum < numfrag; fragnum++) {
offset = fragnum*fragcount*ext;
fragcount = count / numfrag;
for (int fragnum = 0 ; fragnum < numfrag ; ++fragnum) {
offset = fragnum * fragcount * ext;
thiscount = fragcount;
if(fragnum == numfrag-1) {
if(fragnum == numfrag - 1) {
/* last fragment may not be full */
thiscount = count-fragcount*fragnum;
thiscount = count - fragcount * fragnum;
}
/* last node does not recv */
if(vrank != p-1) {
res = NBC_Sched_recv((char*)offset, true, thiscount, datatype, rpeer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (vrank != p-1) {
res = NBC_Sched_recv ((char *) offset, true, thiscount, datatype, rpeer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
/* root reduces into receivebuf */
if(vrank == 0) {
res = NBC_Sched_op((char*)recvbuf+offset, false, (char*)sendbuf+offset, false, (char*)offset, true, thiscount, datatype, op, schedule);
res = NBC_Sched_op ((char *) recvbuf + offset, false, (char *) sendbuf + offset, false, (char *) offset, true,
thiscount, datatype, op, schedule, true);
} else {
res = NBC_Sched_op((char*)offset, true, (char*)sendbuf+offset, false, (char*)offset, true, thiscount, datatype, op, schedule);
res = NBC_Sched_op ((char *) offset, true, (char *) sendbuf + offset, false, (char *) offset, true, thiscount,
datatype, op, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
res = NBC_Sched_barrier(schedule);
}
/* root does not send */
if(vrank != 0) {
if (vrank != 0) {
/* rank p-1 has to send out of sendbuffer :) */
if(vrank == p-1) {
res = NBC_Sched_send((char*)sendbuf+offset, false, thiscount, datatype, speer, schedule);
/* the barrier here seems awkward but isn't!!!! */
if (vrank == p-1) {
res = NBC_Sched_send ((char *) sendbuf + offset, false, thiscount, datatype, speer, schedule, true);
} else {
res = NBC_Sched_send((char*)offset, true, thiscount, datatype, speer, schedule);
res = NBC_Sched_send ((char *) offset, true, thiscount, datatype, speer, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
/* this barrier here seems awkward but isn't!!!! */
res = NBC_Sched_barrier(schedule);
}
}
return NBC_OK;
return OMPI_SUCCESS;
}
/* simple linear algorithm for intercommunicators */
static inline int red_sched_linear(int rank, int rsize, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle) {
int res, peer;
static inline int red_sched_linear (int rank, int rsize, int root, void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, NBC_Schedule *schedule, NBC_Handle *handle) {
int res;
if(count == 0) return NBC_OK;
if (MPI_ROOT == root) {
res = NBC_Sched_recv (recvbuf, false, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier (schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
for (peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv (0, true, count, datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_op (recvbuf, false, 0, true, recvbuf, false, count, datatype, op, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
} else if (MPI_PROC_NULL != root) {
res = NBC_Sched_send (sendbuf, false, count, datatype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (0 == count) {
return OMPI_SUCCESS;
}
return NBC_OK;
if (MPI_ROOT == root) {
res = NBC_Sched_recv (recvbuf, false, count, datatype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
for (int peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv (0, true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
res = NBC_Sched_op (recvbuf, false, 0, true, recvbuf, false, count, datatype, op, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
} else if (MPI_PROC_NULL != root) {
res = NBC_Sched_send (sendbuf, false, count, datatype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014-2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
@ -37,220 +38,285 @@
int ompi_coll_libnbc_ireduce_scatter(void* sendbuf, void* recvbuf, int *recvcounts, MPI_Datatype datatype,
MPI_Op op, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int peer, rank, maxr, p, r, res, count, offset, firstred;
int peer, rank, maxr, p, res, count;
MPI_Aint ext;
char *redbuf, *sbuf, inplace;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
if(p==1) {
if(!inplace) {
/* single node not in_place: copy data to recvbuf */
res = NBC_Copy(sendbuf, recvcounts[0], datatype, recvbuf, recvcounts[0], datatype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
}
/* manually complete the request */
(*request)->req_status.MPI_ERROR = OMPI_SUCCESS;
OPAL_THREAD_LOCK(&ompi_request_lock);
ompi_request_complete(*request, true);
OPAL_THREAD_UNLOCK(&ompi_request_lock);
return NBC_OK;
res = MPI_Type_extent (datatype, &ext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return NBC_OOR; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
maxr = (int)ceil((log((double)p)/LOG2));
count = 0;
for(r=0;r<p;r++) count += recvcounts[r];
for (int r = 0 ; r < p ; ++r) {
count += recvcounts[r];
}
handle->tmpbuf = malloc(ext*count*2);
if(handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
if (p == 1 || 0 == count) {
if (!inplace) {
/* single node not in_place: copy data to recvbuf */
res = NBC_Copy(sendbuf, recvcounts[0], datatype, recvbuf, recvcounts[0], datatype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
redbuf = ((char*)handle->tmpbuf)+(ext*count);
*request = &ompi_request_empty;
return OMPI_SUCCESS;
}
firstred = 1;
for(r=1; r<=maxr; r++) {
if((rank % (1<<r)) == 0) {
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
maxr = (int) ceil ((log((double) p) / LOG2));
handle->tmpbuf = malloc (ext * count * 2);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
redbuf = (char *) handle->tmpbuf + ext * count;
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
for (int r = 1, firstred = 1 ; r <= maxr ; ++r) {
if ((rank % (1 << r)) == 0) {
/* we have to receive this round */
peer = rank + (1<<(r-1));
if(peer<p) {
res = NBC_Sched_recv(0, true, count, datatype, peer, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
peer = rank + (1 << (r - 1));
if (peer < p) {
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if(firstred) {
res = NBC_Sched_recv(0, true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* this cannot be done until handle->tmpbuf is unused :-( so barrier after the op */
if (firstred) {
/* take reduce data from the sendbuf in the first round -> save copy */
res = NBC_Sched_op(redbuf-(unsigned long)handle->tmpbuf, true, sendbuf, false, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (redbuf - (intptr_t) handle->tmpbuf, true, sendbuf, false, 0, true, count, datatype,
op, schedule, true);
firstred = 0;
} else {
/* perform the reduce in my local buffer */
res = NBC_Sched_op(redbuf-(unsigned long)handle->tmpbuf, true, redbuf-(unsigned long)handle->tmpbuf, true, 0, true, count, datatype, op, schedule);
res = NBC_Sched_op (redbuf - (intptr_t) handle->tmpbuf, true, redbuf - (intptr_t) handle->tmpbuf, true,
0, true, count, datatype, op, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
} else {
/* we have to send this round */
peer = rank - (1<<(r-1));
if(firstred) {
peer = rank - (1 << (r - 1));
if (firstred) {
/* we have to send the senbuf */
res = NBC_Sched_send(sendbuf, false, count, datatype, peer, schedule);
res = NBC_Sched_send (sendbuf, false, count, datatype, peer, schedule, false);
} else {
/* we send an already reduced value from redbuf */
res = NBC_Sched_send(redbuf-(unsigned long)handle->tmpbuf, true, count, datatype, peer, schedule);
res = NBC_Sched_send (redbuf - (intptr_t) handle->tmpbuf, true, count, datatype, peer, schedule, false);
}
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* leave the game */
break;
}
}
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* rank 0 is root and sends - all others receive */
if(rank != 0) {
res = NBC_Sched_recv(recvbuf, false, recvcounts[rank], datatype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
}
if(rank == 0) {
offset = 0;
for(r=1;r<p;r++) {
if (rank == 0) {
for (long int r = 1, offset = 0 ; r < p ; ++r) {
offset += recvcounts[r-1];
sbuf = ((char *)redbuf) + (offset*ext);
sbuf = redbuf + offset * ext;
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf-(unsigned long)handle->tmpbuf, true, recvcounts[r], datatype, r, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sbuf - (intptr_t) handle->tmpbuf, true, recvcounts[r], datatype, r, schedule,
false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
res = NBC_Sched_copy(redbuf-(unsigned long)handle->tmpbuf, true, recvcounts[0], datatype, recvbuf, false, recvcounts[0], datatype, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_copy() (%i)\n", res); return res; }
res = NBC_Sched_copy (redbuf - (intptr_t) handle->tmpbuf, true, recvcounts[0], datatype, recvbuf, false,
recvcounts[0], datatype, schedule, false);
} else {
res = NBC_Sched_recv (recvbuf, false, recvcounts[rank], datatype, 0, schedule, false);
}
/*NBC_PRINT_SCHED(*schedule);*/
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_ireduce_scatter_inter(void* sendbuf, void* recvbuf, int *recvcounts, MPI_Datatype datatype,
MPI_Op op, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int peer, rank, r, res, count, rsize, offset;
int ompi_coll_libnbc_ireduce_scatter_inter (void* sendbuf, void* recvbuf, int *recvcounts, MPI_Datatype datatype,
MPI_Op op, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, res, count, rsize;
MPI_Aint ext;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
rsize = ompi_comm_remote_size (comm);
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return NBC_OOR; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
res = MPI_Type_extent (datatype, &ext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
count = 0;
for (r = 0 ; r < rsize ; ++r) count += recvcounts[r];
for (int r = 0 ; r < rsize ; ++r) {
count += recvcounts[r];
}
handle->tmpbuf = malloc(2 * ext * count);
if(handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
if (count > 0) {
handle->tmpbuf = malloc (2 * ext * count);
if (OPAL_UNLIKELY(NULL == handle->tmpbuf)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
}
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
/* send my data to the remote root */
res = NBC_Sched_send(sendbuf, false, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send(sendbuf, false, count, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (0 == rank) {
res = NBC_Sched_recv((void *) 0, true, count, datatype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv ((void *) 0, true, count, datatype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
for (peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv((void *)(ext * count), true, count, datatype, peer, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_op((void *) 0, true, (void *)(ext * count), true, (void *) 0, true, count, datatype, op, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
for (int peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv ((void *)(ext * count), true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_op ((void *) 0, true, (void *)(ext * count), true, (void *) 0, true, count, datatype,
op, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
/* exchange data with remote root for scatter phase (we *could* use the local communicator to do the scatter) */
res = NBC_Sched_recv((void *)(ext * count), true, count, datatype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv ((void *)(ext * count), true, count, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_send((void *) 0, true, count, datatype, 0, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_send ((void *) 0, true, count, datatype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* scatter */
for (peer = 0, offset = ext * count ; peer < rsize ; ++peer) {
res = NBC_Sched_send((void *)(uintptr_t) offset, true, recvcounts[peer], datatype, peer, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
for (int peer = 0, offset = ext * count ; peer < rsize ; ++peer) {
res = NBC_Sched_send ((void *)(uintptr_t) offset, true, recvcounts[peer], datatype, peer, schedule,
false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
offset += recvcounts[peer] * ext;
}
}
/* receive my block */
res = NBC_Sched_recv(recvbuf, false, recvcounts[rank], datatype, 0, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (recvbuf, false, recvcounts[rank], datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -0,0 +1,318 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2012 Sandia National Laboratories. All rights reserved.
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2014-2015 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
*/
#include "nbc_internal.h"
/* an reduce_csttare schedule can not be cached easily because the contents
* ot the recvcount value may change, so a comparison of the address
* would not be sufficient ... we simply do not cache it */
/* binomial reduce to rank 0 followed by a linear scatter ...
*
* Algorithm:
* pairwise exchange
* round r:
* grp = rank % 2^r
* if grp == 0: receive from rank + 2^(r-1) if it exists and reduce value
* if grp == 1: send to rank - 2^(r-1) and exit function
*
* do this for R=log_2(p) rounds
*
*/
int ompi_coll_libnbc_ireduce_scatter_block(void* sendbuf, void* recvbuf, int recvcount, MPI_Datatype datatype,
MPI_Op op, struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int peer, rank, maxr, p, res, count;
MPI_Aint ext;
char *redbuf, *sbuf, inplace;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res || 0 == ext) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i:%i)", res, (int) ext);
return (MPI_SUCCESS == res) ? MPI_ERR_SIZE : res;
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OMPI_SUCCESS != res) {
return res;
}
schedule = OBJ_NEW(NBC_Schedule);
if (NULL == schedule) {
OMPI_COLL_LIBNBC_REQUEST_RETURN(handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
maxr = (int)ceil((log((double)p)/LOG2));
count = p * recvcount;
if (0 < count) {
handle->tmpbuf = malloc (ext*count*2);
if (NULL == handle->tmpbuf) {
OMPI_COLL_LIBNBC_REQUEST_RETURN(handle);
OBJ_RELEASE(schedule);
return OMPI_ERR_OUT_OF_RESOURCE;
}
redbuf = (char *) handle->tmpbuf + ext * count;
/* copy data to redbuf if we only have a single node */
if ((p == 1) && !inplace) {
res = NBC_Copy (sendbuf, count, datatype, redbuf, count, datatype, comm);
if (OMPI_SUCCESS != res) {
NBC_Return_handle (handle);
OBJ_RELEASE(schedule);
return res;
}
*request = &ompi_request_empty;
return OMPI_SUCCESS;
}
for (int r = 1, firstred = 1 ; r <= maxr; ++r) {
if ((rank % (1 << r)) == 0) {
/* we have to receive this round */
peer = rank + (1 << (r - 1));
if (peer < p) {
/* we have to wait until we have the data */
res = NBC_Sched_recv (0, true, count, datatype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (firstred) {
/* take reduce data from the sendbuf in the first round -> save copy */
res = NBC_Sched_op (redbuf-(unsigned long)handle->tmpbuf, true, sendbuf, false, 0, true, count,
datatype, op, schedule, true);
firstred = 0;
} else {
/* perform the reduce in my local buffer */
res = NBC_Sched_op (redbuf-(unsigned long)handle->tmpbuf, true, redbuf-(unsigned long)handle->tmpbuf,
true, 0, true, count, datatype, op, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
} else {
/* we have to send this round */
peer = rank - (1 << (r - 1));
if(firstred) {
/* we have to send the senbuf */
res = NBC_Sched_send (sendbuf, false, count, datatype, peer, schedule, true);
} else {
/* we send an already reduced value from redbuf */
res = NBC_Sched_send (redbuf-(unsigned long)handle->tmpbuf, true, count, datatype, peer, schedule, true);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* leave the game */
break;
}
}
res = NBC_Sched_barrier(schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* rank 0 is root and sends - all others receive */
if (rank != 0) {
res = NBC_Sched_recv (recvbuf, false, recvcount, datatype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
} else {
for (int r = 1, offset = 0 ; r < p ; ++r) {
offset += recvcount;
sbuf = ((char *)redbuf) + (offset*ext);
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send (sbuf-(unsigned long)handle->tmpbuf, true, recvcount, datatype, r, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
res = NBC_Sched_copy (redbuf-(unsigned long)handle->tmpbuf, true, recvcount, datatype, recvbuf, false, recvcount,
datatype, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_ireduce_scatter_block_inter(void *sbuf, void *rbuf, int rcount, struct ompi_datatype_t *dtype,
struct ompi_op_t *op, struct ompi_communicator_t *comm,
ompi_request_t **request, struct mca_coll_base_module_2_1_0_t *module) {
int rank, res, count, rsize;
MPI_Aint ext;
NBC_Schedule *schedule;
NBC_Handle *handle;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
rank = ompi_comm_rank (comm);
rsize = ompi_comm_remote_size (comm);
res = MPI_Type_extent (dtype, &ext);
if (MPI_SUCCESS != res) {
NBC_Error ("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
count = rcount * rsize;
if (count > 0) {
handle->tmpbuf = malloc (2 * ext * count);
if (NULL == handle->tmpbuf) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
}
schedule = OBJ_NEW(NBC_Schedule);
if (NULL == schedule) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* make sure the schedule is released with the handle on error */
handle->schedule = schedule;
/* send my data to the remote root */
res = NBC_Sched_send (sbuf, false, count, dtype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
if (0 == rank) {
res = NBC_Sched_recv ((void *) 0, true, count, dtype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
for (int peer = 1 ; peer < rsize ; ++peer) {
res = NBC_Sched_recv ((void *)(ext * count), true, count, dtype, peer, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_op ((void *) 0, true, (void *)(ext * count), true, (void *) 0, true, count, dtype, op,
schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
/* exchange data with remote root for scatter phase (we *could* use the local communicator to do the scatter) */
res = NBC_Sched_recv ((void *)(ext * count), true, count, dtype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Sched_send ((void *) 0, true, count, dtype, 0, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* scatter */
for (int peer = 0 ; peer < rsize ; ++peer) {
res = NBC_Sched_send ((void *)(ext * (count + peer * rcount)), true, rcount, dtype, peer, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
}
/* receive my block */
res = NBC_Sched_recv(rbuf, true, rcount, dtype, 0, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/*NBC_PRINT_SCHED(*schedule);*/
res = NBC_Sched_commit(schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
res = NBC_Start(handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,3 +1,4 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
@ -6,6 +7,8 @@
* rights reserved.
* Copyright (c) 2014 Research Organization for Information Science
* and Technology (RIST). All rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
@ -15,18 +18,19 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Scan_args_compare(NBC_Scan_args *a, NBC_Scan_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->recvbuf == b->recvbuf) &&
(a->count == b->count) &&
(a->datatype == b->datatype) &&
(a->op == b->op) ) {
return 0;
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if (a->sendbuf < b->sendbuf) {
return -1;
}
return +1;
}
return 1;
}
#endif
@ -43,96 +47,132 @@ int ompi_coll_libnbc_iscan(void* sendbuf, void* recvbuf, int count, MPI_Datatype
int rank, p, res;
MPI_Aint ext;
NBC_Schedule *schedule;
#ifdef NBC_CACHE_SCHEDULE
NBC_Scan_args *args, *found, search;
#endif
char inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
res = MPI_Type_extent(datatype, &ext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
handle->tmpbuf = malloc(ext*count);
if(handle->tmpbuf == NULL) { printf("Error in malloc()\n"); return NBC_OOR; }
res = MPI_Type_extent (datatype, &ext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
if((rank == 0) && !inplace) {
if ((rank == 0) && !inplace) {
/* copy data to receivebuf */
res = NBC_Copy(sendbuf, count, datatype, recvbuf, count, datatype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
res = NBC_Copy (sendbuf, count, datatype, recvbuf, count, datatype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
handle->tmpbuf = malloc (ext * count);
if (NULL == handle->tmpbuf) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
#ifdef NBC_CACHE_SCHEDULE
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.recvbuf=recvbuf;
search.count=count;
search.datatype=datatype;
search.op=op;
found = (NBC_Scan_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCAN], &search);
if(found == NULL) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
NBC_Scan_args *args, *found, search;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* search schedule in communicator specific tree */
search.sendbuf = sendbuf;
search.recvbuf = recvbuf;
search.count = count;
search.datatype = datatype;
search.op = op;
found = (NBC_Scan_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCAN], &search);
if (NULL == found) {
#endif
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
NBC_Return_handle (handle);
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* ensure the schedule is released with the handle */
handle->schedule = schedule;
if(rank != 0) {
res = NBC_Sched_recv(0, true, count, datatype, rank-1, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
/* we have to wait until we have the data */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
res = NBC_Sched_recv (0, true, count, datatype, rank-1, schedule, true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
/* perform the reduce in my local buffer */
res = NBC_Sched_op(recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_op() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( */
res = NBC_Sched_barrier(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_barrier() (%i)\n", res); return res; }
}
if(rank != p-1) {
res = NBC_Sched_send(recvbuf, false, count, datatype, rank+1, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
/* this cannot be done until handle->tmpbuf is unused :-( so barrier after the op */
res = NBC_Sched_op (recvbuf, false, sendbuf, false, 0, true, count, datatype, op, schedule,
true);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (rank != p-1) {
res = NBC_Sched_send (recvbuf, false, count, datatype, rank+1, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
}
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Scan_args*)malloc(sizeof(NBC_Alltoall_args));
args->sendbuf=sendbuf;
args->recvbuf=recvbuf;
args->count=count;
args->datatype=datatype;
args->op=op;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCAN], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_SCAN] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCAN], &handle->comminfo->NBC_Dict_size[NBC_SCAN]);
args = (NBC_Scan_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->recvbuf = recvbuf;
args->count = count;
args->datatype = datatype;
args->op = op;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCAN], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_SCAN] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCAN],
&libnbc_module->NBC_Dict_size[NBC_SCAN]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { free(handle->tmpbuf); printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
/* tmpbuf is freed with the handle */
return NBC_OK;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2013 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
@ -20,62 +21,61 @@
#ifdef NBC_CACHE_SCHEDULE
/* tree comparison function for schedule cache */
int NBC_Scatter_args_compare(NBC_Scatter_args *a, NBC_Scatter_args *b, void *param) {
if( (a->sendbuf == b->sendbuf) &&
if ((a->sendbuf == b->sendbuf) &&
(a->sendcount == b->sendcount) &&
(a->sendtype == b->sendtype) &&
(a->recvbuf == b->recvbuf) &&
(a->recvcount == b->recvcount) &&
(a->recvtype == b->recvtype) &&
(a->root == b->root) ) {
return 0;
(a->root == b->root)) {
return 0;
}
if( a->sendbuf < b->sendbuf ) {
if (a->sendbuf < b->sendbuf) {
return -1;
}
return +1;
return 1;
}
#endif
/* simple linear MPI_Iscatter */
int ompi_coll_libnbc_iscatter(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i;
int ompi_coll_libnbc_iscatter (void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res;
MPI_Aint sndext = 0;
NBC_Schedule *schedule;
char *sbuf, inplace;
#ifdef NBC_CACHE_SCHEDULE
NBC_Scatter_args *args, *found, search;
#endif
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
if (rank == root) {
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
res = MPI_Type_extent (sendtype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
handle->tmpbuf=NULL;
if((rank == root) && (!inplace)) {
sbuf = ((char *)sendbuf) + (rank*sendcount*sndext);
if ((rank == root) && (!inplace)) {
sbuf = (char *) sendbuf + rank * sendcount * sndext;
/* if I am the root - just copy the message (not for MPI_IN_PLACE) */
res = NBC_Copy(sbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
res = NBC_Copy (sbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
return res;
}
}
#ifdef NBC_CACHE_SCHEDULE
NBC_Scatter_args *args, *found, search;
/* search schedule in communicator specific tree */
search.sendbuf=sendbuf;
search.sendcount=sendcount;
@ -84,114 +84,156 @@ int ompi_coll_libnbc_iscatter(void* sendbuf, int sendcount, MPI_Datatype sendtyp
search.recvcount=recvcount;
search.recvtype=recvtype;
search.root=root;
found = (NBC_Scatter_args*)hb_tree_search((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCATTER], &search);
if(found == NULL) {
found = (NBC_Scatter_args *) hb_tree_search ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCATTER], &search);
if (NULL == found) {
#endif
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* receive from root */
if(rank != root) {
if (rank != root) {
/* recv msg from root */
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv (recvbuf, false, recvcount, recvtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else {
for(i=0;i<p;i++) {
sbuf = ((char *)sendbuf) + (i*sendcount*sndext);
if(i != root) {
for (int i = 0 ; i < p ; ++i) {
sbuf = (char *) sendbuf + i * sendcount * sndext;
if (i != root) {
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sbuf, false, sendcount, sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
#ifdef NBC_CACHE_SCHEDULE
/* save schedule to tree */
args = (NBC_Scatter_args*)malloc(sizeof(NBC_Scatter_args));
args->sendbuf=sendbuf;
args->sendcount=sendcount;
args->sendtype=sendtype;
args->recvbuf=recvbuf;
args->recvcount=recvcount;
args->recvtype=recvtype;
args->root=root;
args->schedule=schedule;
res = hb_tree_insert ((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCATTER], args, args, 0);
if(res != 0) printf("error in dict_insert() (%i)\n", res);
/* increase number of elements for A2A */
if(++handle->comminfo->NBC_Dict_size[NBC_SCATTER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe((hb_tree*)handle->comminfo->NBC_Dict[NBC_SCATTER], &handle->comminfo->NBC_Dict_size[NBC_SCATTER]);
args = (NBC_Scatter_args *) malloc (sizeof (args));
if (NULL != args) {
args->sendbuf = sendbuf;
args->sendcount = sendcount;
args->sendtype = sendtype;
args->recvbuf = recvbuf;
args->recvcount = recvcount;
args->recvtype = recvtype;
args->root = root;
args->schedule = schedule;
res = hb_tree_insert ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCATTER], args, args, 0);
if (0 == res) {
OBJ_RETAIN(schedule);
/* increase number of elements for A2A */
if (++libnbc_module->NBC_Dict_size[NBC_SCATTER] > NBC_SCHED_DICT_UPPER) {
NBC_SchedCache_dictwipe ((hb_tree *) libnbc_module->NBC_Dict[NBC_SCATTER],
&libnbc_module->NBC_Dict_size[NBC_SCATTER]);
}
} else {
NBC_Error("error in dict_insert() (%i)", res);
free (args);
}
}
} else {
/* found schedule */
schedule=found->schedule;
schedule = found->schedule;
OBJ_RETAIN(schedule);
}
#endif
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_iscatter_inter(void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, res, i, rsize;
int ompi_coll_libnbc_iscatter_inter (void* sendbuf, int sendcount, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int res, rsize;
MPI_Aint sndext;
NBC_Schedule *schedule;
char *sbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
if (MPI_ROOT == root) {
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
return res;
}
}
res = MPI_Comm_remote_size (comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
/* receive from root */
if (MPI_ROOT != root && MPI_PROC_NULL != root) {
/* recv msg from remote root */
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else if (MPI_ROOT == root) {
for (i = 0 ; i < rsize ; ++i) {
for (int i = 0 ; i < rsize ; ++i) {
sbuf = ((char *)sendbuf) + (i * sendcount * sndext);
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send(sbuf, false, sendcount, sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,10 +1,11 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2013 Los Alamos National Security, LLC. All rights
* Copyright (c) 2013-2015 Los Alamos National Security, LLC. All rights
* reserved.
* Copyright (c) 2013 The University of Tennessee and The University
* of Tennessee Research Foundation. All rights
@ -26,117 +27,147 @@ int ompi_coll_libnbc_iscatterv(void* sendbuf, int *sendcounts, int *displs, MPI_
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, p, res, i;
int rank, p, res;
MPI_Aint sndext;
NBC_Schedule *schedule;
char *sbuf, inplace;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
NBC_IN_PLACE(sendbuf, recvbuf, inplace);
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
res = MPI_Comm_size(comm, &p);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_size() (%i)\n", res); return res; }
if (rank == root) {
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
p = ompi_comm_size (comm);
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
handle->tmpbuf=NULL;
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* receive from root */
if(rank != root) {
/* recv msg from root */
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
} else {
for(i=0;i<p;i++) {
sbuf = ((char *)sendbuf) + (displs[i]*sndext);
if(i == root) {
if(!inplace) {
if (rank == root) {
res = MPI_Type_extent (sendtype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
OBJ_RELEASE(schedule);
return res;
}
for (int i = 0 ; i < p ; ++i) {
sbuf = (char *) sendbuf + displs[i] * sndext;
if (i == root) {
if (!inplace) {
/* if I am the root - just copy the message */
res = NBC_Copy(sbuf, sendcounts[i], sendtype, recvbuf, recvcount, recvtype, comm);
if (NBC_OK != res) { printf("Error in NBC_Copy() (%i)\n", res); return res; }
res = NBC_Copy (sbuf, sendcounts[i], sendtype, recvbuf, recvcount, recvtype, comm);
} else {
res = OMPI_SUCCESS;
}
} else {
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtype, i, schedule, false);
}
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
} else {
/* recv msg from root */
res = NBC_Sched_recv (recvbuf, false, recvcount, recvtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
res = NBC_Sched_commit (schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
res = NBC_Init_handle (comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
return NBC_OK;
res = NBC_Start (handle, schedule);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}
int ompi_coll_libnbc_iscatterv_inter (void* sendbuf, int *sendcounts, int *displs, MPI_Datatype sendtype,
void* recvbuf, int recvcount, MPI_Datatype recvtype, int root,
struct ompi_communicator_t *comm, ompi_request_t ** request,
struct mca_coll_base_module_2_1_0_t *module) {
int rank, res, i, rsize;
int res, rsize;
MPI_Aint sndext;
NBC_Schedule *schedule;
char *sbuf;
NBC_Handle *handle;
ompi_coll_libnbc_request_t **coll_req = (ompi_coll_libnbc_request_t**) request;
ompi_coll_libnbc_module_t *libnbc_module = (ompi_coll_libnbc_module_t*) module;
res = NBC_Init_handle(comm, coll_req, libnbc_module);
if(res != NBC_OK) { printf("Error in NBC_Init_handle(%i)\n", res); return res; }
handle = (*coll_req);
res = MPI_Comm_rank(comm, &rank);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_rank() (%i)\n", res); return res; }
if (MPI_ROOT == root) {
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Type_extent() (%i)\n", res); return res; }
rsize = ompi_comm_remote_size (comm);
schedule = OBJ_NEW(NBC_Schedule);
if (OPAL_UNLIKELY(NULL == schedule)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
res = MPI_Comm_remote_size(comm, &rsize);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Comm_remote_size() (%i)\n", res); return res; }
handle->tmpbuf = NULL;
schedule = (NBC_Schedule*)malloc(sizeof(NBC_Schedule));
if (NULL == schedule) { printf("Error in malloc()\n"); return res; }
res = NBC_Sched_create(schedule);
if(res != NBC_OK) { printf("Error in NBC_Sched_create (%i)\n", res); return res; }
/* receive from root */
if (MPI_ROOT != root && MPI_PROC_NULL != root) {
/* recv msg from root */
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_recv() (%i)\n", res); return res; }
res = NBC_Sched_recv(recvbuf, false, recvcount, recvtype, root, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
} else if (MPI_ROOT == root) {
for (i = 0 ; i < rsize ; ++i) {
sbuf = ((char *)sendbuf) + (displs[i] * sndext);
res = MPI_Type_extent(sendtype, &sndext);
if (MPI_SUCCESS != res) {
NBC_Error("MPI Error in MPI_Type_extent() (%i)", res);
OBJ_RELEASE(schedule);
return res;
}
for (int i = 0 ; i < rsize ; ++i) {
sbuf = (char *)sendbuf + displs[i] * sndext;
/* root sends the right buffer to the right receiver */
res = NBC_Sched_send(sbuf, false, sendcounts[i], sendtype, i, schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_send() (%i)\n", res); return res; }
res = NBC_Sched_send (sbuf, false, sendcounts[i], sendtype, i, schedule, false);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
}
}
res = NBC_Sched_commit(schedule);
if (NBC_OK != res) { printf("Error in NBC_Sched_commit() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Init_handle(comm, &handle, libnbc_module);
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
OBJ_RELEASE(schedule);
return res;
}
res = NBC_Start(handle, schedule);
if (NBC_OK != res) { printf("Error in NBC_Start() (%i)\n", res); return res; }
if (OPAL_UNLIKELY(OMPI_SUCCESS != res)) {
NBC_Return_handle (handle);
return res;
}
return NBC_OK;
*request = (ompi_request_t *) handle;
return OMPI_SUCCESS;
}

Просмотреть файл

@ -1,106 +1,103 @@
/* -*- Mode: C; c-basic-offset:2 ; indent-tabs-mode:nil -*- */
/*
* Copyright (c) 2006 The Trustees of Indiana University and Indiana
* University Research and Technology
* Corporation. All rights reserved.
* Copyright (c) 2006 The Technical University of Chemnitz. All
* rights reserved.
* Copyright (c) 2015 Los Alamos National Security, LLC. All rights
* reserved.
*
* Author(s): Torsten Hoefler <htor@cs.indiana.edu>
*
*/
#include "nbc_internal.h"
#include "ompi/mca/topo/base/base.h"
int NBC_Comm_neighbors_count(MPI_Comm comm, int *indegree, int *outdegree, int *weighted) {
int topo, res;
int NBC_Comm_neighbors_count (ompi_communicator_t *comm, int *indegree, int *outdegree) {
if (OMPI_COMM_IS_CART(comm)) {
/* cartesian */
/* outdegree is always 2*ndims because we need to iterate over empty buffers for MPI_PROC_NULL */
*outdegree = *indegree = 2 * comm->c_topo->mtc.cart->ndims;
} else if (OMPI_COMM_IS_GRAPH(comm)) {
/* graph */
int rank, nneighbors;
res = MPI_Topo_test(comm, &topo);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Topo_test() (%i)\n", res); return res; }
rank = ompi_comm_rank (comm);
mca_topo_base_graph_neighbors_count (comm, rank, &nneighbors);
switch(topo) {
case MPI_CART: /* cartesian */
{
int ndims;
res = MPI_Cartdim_get(comm, &ndims) ;
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cartdim_get() (%i)\n", res); return res; }
/* outdegree is always 2*ndims because we need to iterate over empty buffers for MPI_PROC_NULL */
*outdegree = *indegree = 2*ndims;
*weighted = 0;
}
break;
case MPI_GRAPH: /* graph */
{
int rank, nneighbors;
MPI_Comm_rank(comm, &rank);
res = MPI_Graph_neighbors_count(comm, rank, &nneighbors);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Graph_neighbors_count() (%i)\n", res); return res; }
*outdegree = *indegree = nneighbors;
*weighted = 0;
}
break;
case MPI_DIST_GRAPH: /* graph */
{
res = MPI_Dist_graph_neighbors_count(comm, indegree, outdegree, weighted);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Dist_graph_neighbors_count() (%i)\n", res); return res; }
}
break;
case MPI_UNDEFINED:
return NBC_INVALID_TOPOLOGY_COMM;
break;
default:
return NBC_INVALID_PARAM;
break;
}
return NBC_OK;
}
int NBC_Comm_neighbors(MPI_Comm comm, int maxindegree, int sources[], int sourceweights[], int maxoutdegree, int destinations[], int destweights[]) {
int topo, res;
int index = 0;
int indeg, outdeg, wgtd;
res = NBC_Comm_neighbors_count(comm, &indeg, &outdeg, &wgtd);
if(indeg > maxindegree && outdeg > maxoutdegree) return NBC_INVALID_PARAM; /* we want to return *all* neighbors */
res = MPI_Topo_test(comm, &topo);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Topo_test() (%i)\n", res); return res; }
switch(topo) {
case MPI_CART: /* cartesian */
{
int ndims, i, rpeer, speer;
res = MPI_Cartdim_get(comm, &ndims);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cartdim_get() (%i)\n", res); return res; }
for(i = 0; i<ndims; i++) {
res = MPI_Cart_shift(comm, i, 1, &rpeer, &speer);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Cart_shift() (%i)\n", res); return res; }
sources[index] = destinations[index] = rpeer; index++;
sources[index] = destinations[index] = speer; index++;
}
}
break;
case MPI_GRAPH: /* graph */
{
int rank;
MPI_Comm_rank(comm, &rank);
res = MPI_Graph_neighbors(comm, rank, maxindegree, sources);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Graph_neighbors_count() (%i)\n", res); return res; }
for(int i=0; i<maxindegree; i++) destinations[i] = sources[i];
}
break;
case MPI_DIST_GRAPH: /* dist graph */
{
res = MPI_Dist_graph_neighbors(comm, maxindegree, sources, sourceweights, maxoutdegree, destinations, destweights);
if (MPI_SUCCESS != res) { printf("MPI Error in MPI_Graph_neighbors_count() (%i)\n", res); return res; }
}
break;
case MPI_UNDEFINED:
return NBC_INVALID_TOPOLOGY_COMM;
break;
default:
return NBC_INVALID_PARAM;
break;
*outdegree = *indegree = nneighbors;
} else if (OMPI_COMM_IS_DIST_GRAPH(comm)) {
/* graph */
*indegree = comm->c_topo->mtc.dist_graph->indegree;
*outdegree = comm->c_topo->mtc.dist_graph->outdegree;
} else {
return OMPI_ERR_BAD_PARAM;
}
return NBC_OK;
return OMPI_SUCCESS;
}
int NBC_Comm_neighbors (ompi_communicator_t *comm, int **sources, int *source_count, int **destinations, int *dest_count) {
int res, indeg, outdeg;
*sources = *destinations = NULL;
res = NBC_Comm_neighbors_count(comm, &indeg, &outdeg);
if (OMPI_SUCCESS != res) {
return res;
}
*source_count = indeg;
*dest_count = outdeg;
if (indeg) {
*sources = malloc (sizeof (int) * indeg);
if (OPAL_UNLIKELY(NULL == *sources)) {
return OMPI_ERR_OUT_OF_RESOURCE;
}
} else {
*sources = NULL;
}
if (outdeg) {
*destinations = malloc (sizeof (int) * outdeg);
if (OPAL_UNLIKELY(NULL == *destinations)) {
free (*sources);
*sources = NULL;
return OMPI_ERR_OUT_OF_RESOURCE;
}
} else {
*destinations = NULL;
}
/* silence clang static analyzer warning about NULL-dereference */
if (0 == indeg && 0 == outdeg) {
return OMPI_SUCCESS;
}
if (OMPI_COMM_IS_CART(comm)) {
/* cartesian */
int rpeer, speer;
/* silence clang static analyzer warning */
assert (indeg == outdeg);
for (int dim = 0, i = 0 ; dim < comm->c_topo->mtc.cart->ndims ; ++dim) {
mca_topo_base_cart_shift (comm, dim, 1, &rpeer, &speer);
sources[0][i] = destinations[0][i] = rpeer; i++;
sources[0][i] = destinations[0][i] = speer; i++;
}
} else if (OMPI_COMM_IS_GRAPH(comm)) {
/* graph */
mca_topo_base_graph_neighbors (comm, ompi_comm_rank (comm), indeg, sources[0]);
memcpy (destinations[0], sources[0], indeg * sizeof (int));
} else if (OMPI_COMM_IS_DIST_GRAPH(comm)) {
/* dist graph */
mca_topo_base_dist_graph_neighbors (comm, indeg, sources[0], MPI_UNWEIGHTED, outdeg, destinations[0],
MPI_UNWEIGHTED);
}
return OMPI_SUCCESS;
}