1 #include <../../nrnconf.h> 10 #if NRNMPI_DYNAMICLOAD 11 #include <nrnmpi_dynam.h> 28 static MPI_Datatype spike_type;
30 static void pgvts_op(
double* in,
double* inout,
int* len, MPI_Datatype* dptr);
31 static MPI_Op mpi_pgvts_op;
33 static void make_spike_type() {
36 MPI_Aint displacements[2];
37 MPI_Aint addresses[3];
38 MPI_Datatype typelist[2];
40 typelist[0] = MPI_INT;
41 typelist[1] = MPI_DOUBLE;
43 block_lengths[0] = block_lengths[1] = 1;
45 MPI_Get_address(&s, &addresses[0]);
46 MPI_Get_address(&(s.
gid), &addresses[1]);
47 MPI_Get_address(&(s.
spiketime), &addresses[2]);
49 displacements[0] = addresses[1] - addresses[0];
50 displacements[1] = addresses[2] - addresses[0];
52 MPI_Type_create_struct(2, block_lengths, displacements, typelist, &spike_type);
53 MPI_Type_commit(&spike_type);
55 MPI_Op_create((MPI_User_function*)pgvts_op, 1, &mpi_pgvts_op);
58 void nrnmpi_spike_initialize() {
62 #if nrn_spikebuf_size > 0 64 static MPI_Datatype spikebuf_type;
66 static void make_spikebuf_type() {
69 MPI_Aint displacements[3];
70 MPI_Aint addresses[4];
71 MPI_Datatype typelist[3];
73 typelist[0] = MPI_INT;
74 typelist[1] = MPI_INT;
75 typelist[2] = MPI_DOUBLE;
81 MPI_Get_address(&s, &addresses[0]);
82 MPI_Get_address(&(s.nspike), &addresses[1]);
83 MPI_Get_address(&(s.gid[0]), &addresses[2]);
84 MPI_Get_address(&(s.spiketime[0]), &addresses[3]);
86 displacements[0] = addresses[1] - addresses[0];
87 displacements[1] = addresses[2] - addresses[0];
88 displacements[2] = addresses[3] - addresses[0];
90 MPI_Type_create_struct(3, block_lengths, displacements, typelist, &spikebuf_type);
91 MPI_Type_commit(&spikebuf_type);
95 int nrnmpi_spike_exchange() {
101 #if nrn_spikebuf_size > 0 102 make_spikebuf_type();
106 #if nrn_spikebuf_size == 0 109 for (i=1; i < np; ++
i) {
122 MPI_Allgather(spbufout_, 1, spikebuf_type, spbufin_, 1, spikebuf_type,
nrnmpi_comm);
124 n = spbufin_[0].nspike;
131 for (i=1; i < np; ++
i) {
133 n1 = spbufin_[
i].nspike;
174 int nrnmpi_spike_exchange_compressed() {
175 int i, novfl,
n, ntot, idx, bs, bstot;
190 for (i=0; i < np; ++
i) {
225 double nrnmpi_mindelay(
double m) {
229 MPI_Allreduce(&m, &result, 1, MPI_DOUBLE, MPI_MIN,
nrnmpi_comm);
237 MPI_Allreduce(&x, &result, 1, MPI_INT, MPI_MAX,
nrnmpi_comm);
241 #define ALLTOALLV_SPARSE_TAG 101980 245 static int MPI_Alltoallv_sparse(
void *sendbuf,
int *sendcnts,
int *sdispls,
246 MPI_Datatype sendtype,
void *recvbuf,
int *recvcnts,
247 int *rdispls, MPI_Datatype recvtype, MPI_Comm comm)
253 status = MPI_Comm_rank(comm, &myrank);
254 assert(status == MPI_SUCCESS);
255 status = MPI_Comm_size(comm, &nranks);
256 assert(status == MPI_SUCCESS);
259 for(rankp = 0; nranks > (1 << rankp); rankp++);
262 ptrdiff_t send_elsize;
263 ptrdiff_t recv_elsize;
265 status = MPI_Type_get_extent(sendtype, &lb, &send_elsize);
266 assert(status == MPI_SUCCESS);
267 status = MPI_Type_get_extent(recvtype, &lb, &recv_elsize);
268 assert(status == MPI_SUCCESS);
273 int ngrp;
int n_requests;
275 for(ngrp = 0; ngrp < (1 << rankp); ngrp++)
277 int target = myrank ^ ngrp;
279 if(target >= nranks)
continue;
280 if(recvcnts[target] == 0)
continue;
281 status = MPI_Irecv((static_cast<char*>(recvbuf)) + recv_elsize * rdispls[target],
283 recvtype, target, ALLTOALLV_SPARSE_TAG, comm, &requests[n_requests++]);
284 assert(status == MPI_SUCCESS);
287 status = MPI_Barrier(comm);
288 assert(status == MPI_SUCCESS);
290 for(ngrp = 0; ngrp < (1 << rankp); ngrp++)
292 int target = myrank ^ ngrp;
293 if(target >= nranks)
continue;
294 if(sendcnts[target] == 0)
continue;
295 status = MPI_Isend((static_cast<char*>(sendbuf)) + send_elsize * sdispls[target],
297 sendtype, target, ALLTOALLV_SPARSE_TAG, comm, &requests[n_requests++]);
298 assert(status == MPI_SUCCESS);
301 status = MPI_Waitall(n_requests, requests, MPI_STATUSES_IGNORE);
302 assert(status == MPI_SUCCESS);
305 status = MPI_Barrier(comm);
306 assert(status == MPI_SUCCESS);
312 extern void nrnmpi_dbl_alltoallv_sparse(
double* s,
int* scnt,
int* sdispl,
double* r,
int* rcnt,
int* rdispl) {
313 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_DOUBLE, r, rcnt, rdispl, MPI_DOUBLE,
nrnmpi_comm);
315 extern void nrnmpi_int_alltoallv_sparse(
int* s,
int* scnt,
int* sdispl,
int* r,
int* rcnt,
int* rdispl) {
316 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_INT, r, rcnt, rdispl, MPI_INT,
nrnmpi_comm);
319 extern void nrnmpi_long_alltoallv_sparse(int64_t* s,
int* scnt,
int* sdispl, int64_t* r,
int* rcnt,
int* rdispl) {
320 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_INT64_T, r, rcnt, rdispl, MPI_INT64_T,
nrnmpi_comm);
325 extern void nrnmpi_int_gather(
int* s,
int* r,
int cnt,
int root) {
326 MPI_Gather(s, cnt, MPI_INT, r, cnt, MPI_INT, root,
nrnmpi_comm);
329 extern void nrnmpi_int_gatherv(
int* s,
int scnt,
330 int* r,
int* rcnt,
int* rdispl,
int root) {
331 MPI_Gatherv(s, scnt, MPI_INT,
335 extern void nrnmpi_char_gatherv(
char* s,
int scnt,
336 char* r,
int* rcnt,
int* rdispl,
int root) {
337 MPI_Gatherv(s, scnt, MPI_CHAR,
341 extern void nrnmpi_int_scatter(
int* s,
int* r,
int cnt,
int root) {
342 MPI_Scatter(s, cnt, MPI_INT, r, cnt, MPI_INT, root,
nrnmpi_comm);
345 extern void nrnmpi_char_scatterv(
char* s,
int* scnt,
int* sdispl,
char* r,
int rcnt,
int root) {
346 MPI_Scatterv(s, scnt, sdispl, MPI_CHAR, r, rcnt, MPI_CHAR, root,
nrnmpi_comm);
349 extern void nrnmpi_int_alltoall(
int* s,
int* r,
int n) {
350 MPI_Alltoall(s, n, MPI_INT, r, n, MPI_INT,
nrnmpi_comm);
354 int* r,
int* rcnt,
int* rdispl) {
355 MPI_Alltoallv(s, scnt, sdispl, MPI_INT,
359 extern void nrnmpi_long_alltoallv(int64_t* s,
int* scnt,
int* sdispl,
360 int64_t* r,
int* rcnt,
int* rdispl) {
361 MPI_Alltoallv(s, scnt, sdispl, MPI_INT64_T,
366 double* r,
int* rcnt,
int* rdispl) {
367 MPI_Alltoallv(s, scnt, sdispl, MPI_DOUBLE,
371 extern void nrnmpi_char_alltoallv(
char* s,
int* scnt,
int* sdispl,
372 char* r,
int* rcnt,
int* rdispl) {
373 MPI_Alltoallv(s, scnt, sdispl, MPI_CHAR,
380 MPI_Allgather(s, n, MPI_INT, r, n, MPI_INT,
nrnmpi_comm);
383 void nrnmpi_int_allgather_inplace(
int* srcdest,
int n) {
384 MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest, n, MPI_INT,
nrnmpi_comm);
392 void nrnmpi_int_allgatherv_inplace(
int* srcdest,
int* n,
int* dspl) {
393 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
397 void nrnmpi_char_allgatherv(
char* s,
char* r,
int* n,
int* dspl) {
402 void nrnmpi_long_allgatherv(int64_t* s, int64_t* r,
int* n,
int* dspl) {
407 void nrnmpi_long_allgatherv_inplace(
long* srcdest,
int* n,
int* dspl) {
408 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
417 void nrnmpi_dbl_allgatherv_inplace(
double* srcdest,
int* n,
int* dspl) {
418 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
423 MPI_Bcast(buf, cnt, MPI_DOUBLE, root,
nrnmpi_comm);
434 void nrnmpi_char_broadcast_world(
char** pstr,
int root) {
436 sz = *pstr ? (strlen(*pstr) + 1) : 0;
439 if (*pstr) { free(*pstr); *pstr =
NULL; }
449 int nrnmpi_int_sum_reduce(
int in) {
451 MPI_Allreduce(&in, &result, 1, MPI_INT, MPI_SUM,
nrnmpi_comm);
455 void nrnmpi_assert_opstep(
int opstep,
double t) {
459 buf[0] = (double)opstep;
462 if (opstep != (
int)buf[0] || t != buf[1]) {
464 (
int)buf[0], t, t-buf[1]);
469 double nrnmpi_dbl_allmin(
double x) {
472 MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, MPI_MIN,
nrnmpi_comm);
476 static void pgvts_op(
double* in,
double* inout,
int* len, MPI_Datatype* dptr){
478 assert(*dptr == MPI_DOUBLE);
480 if (in[0] < inout[0]) {
483 }
else if (in[0] == inout[0]) {
485 if (in[1] < inout[1]) {
488 }
else if (in[1] == inout[1]) {
490 if (in[2] < inout[2]) {
493 }
else if (in[2] == inout[2]) {
495 if (in[3] < inout[3]) {
503 for (i=0; i < 4; ++
i) { inout[
i] = in[
i]; }
507 int nrnmpi_pgvts_least(
double* t,
int* op,
int*
init) {
509 double ibuf[4], obuf[4];
511 ibuf[1] = (double)(*op);
512 ibuf[2] = (double)(*init);
514 for (i=0; i < 4; ++
i) {
517 MPI_Allreduce(ibuf, obuf, 4, MPI_DOUBLE, mpi_pgvts_op,
nrnmpi_comm);
520 assert((
int)obuf[1] <= *op);
521 if ((
int)obuf[1] == *op) {
522 assert((
int)obuf[2] <= *init);
523 if ((
int)obuf[2] == *init) {
530 *init = (
int)obuf[2];
539 MPI_Send(pd, cnt, MPI_DOUBLE, dest, tag,
nrnmpi_comm);
542 void nrnmpi_recv_doubles(
double* pd,
int cnt,
int src,
int tag) {
544 MPI_Recv(pd, cnt, MPI_DOUBLE, src, tag,
nrnmpi_comm, &status);
548 MPI_Irecv(pd, cnt, MPI_DOUBLE, src, tag,
nrnmpi_comm, (MPI_Request*)request);
553 MPI_Wait((MPI_Request*)request, &status);
561 double nrnmpi_dbl_allreduce(
double x,
int type) {
567 }
else if (type == 2) {
572 MPI_Allreduce(&x, &result, 1, MPI_DOUBLE, t,
nrnmpi_comm);
576 extern "C" void nrnmpi_dbl_allreduce_vec(
double* src,
double* dest,
int cnt,
int type) {
581 for (i = 0; i <
cnt; ++
i) {
588 }
else if (type == 2) {
593 MPI_Allreduce(src, dest, cnt, MPI_DOUBLE, t,
nrnmpi_comm);
597 void nrnmpi_longdbl_allreduce_vec(
longdbl* src,
longdbl* dest,
int cnt,
int type) {
602 for (i = 0; i <
cnt; ++
i) {
609 }
else if (type == 2) {
614 MPI_Allreduce(src, dest, cnt, MPI_LONG_DOUBLE, t,
nrnmpi_comm);
618 void nrnmpi_long_allreduce_vec(
long* src,
long* dest,
int cnt,
int type) {
623 for (i = 0; i <
cnt; ++
i) {
630 }
else if (type == 2) {
635 MPI_Allreduce(src, dest, cnt, MPI_LONG, t,
nrnmpi_comm);
639 void nrnmpi_dbl_allgather(
double* s,
double* r,
int n) {
640 MPI_Allgather(s, n, MPI_DOUBLE, r, n, MPI_DOUBLE,
nrnmpi_comm);
645 static MPI_Comm bgp_comm;
657 for (i=0; i <
n; ++
i) {
658 MPI_Isend(spk, 1, spike_type, hosts[i], 1, bgp_comm, &r);
659 MPI_Request_free(&r);
666 MPI_Iprobe(MPI_ANY_SOURCE, 1, bgp_comm, &flag, &status);
668 MPI_Recv(spk, 1, spike_type, MPI_ANY_SOURCE, 1, bgp_comm, &status);
676 tcnts[0] = nsend - nrecv;
677 MPI_Allreduce(tcnts, tcnts+1, 1, MPI_INT, MPI_SUM, bgp_comm);
static int nrnmpi_int_allmax(int x)
static void nrnmpi_int_allgatherv(int *s, int *r, int *n, int *dspl)
static void nrnmpi_char_broadcast(char *, int, int)
void nrnmpi_bgp_multisend(NRNMPI_Spike *, int, int *)
void nrnbbs_context_wait()
unsigned char * spfixin_ovfl_
static void nrnmpi_postrecv_doubles(double *, int, int, int, void **)
int const size_t const size_t n
static void nrnmpi_int_broadcast(int *, int, int)
static void nrnmpi_barrier()
void hoc_execerror(const char *, const char *)
#define nrn_spikebuf_size
static void nrnmpi_int_alltoallv(int *s, int *scnt, int *sdispl, int *r, int *rcnt, int *rdispl)
static void nrnmpi_send_doubles(double *, int, int, int)
unsigned char * spfixout_
static void nrnmpi_int_allgather(int *s, int *r, int n)
int nrnmpi_bgp_conserve(int nsend, int nrecv)
static void nrnmpi_dbl_alltoallv(double *s, int *scnt, int *sdispl, double *r, int *rcnt, int *rdispl)
static void nrnmpi_dbl_broadcast(double *, int, int)
static void nrnmpi_dbl_allgatherv(double *s, double *r, int *n, int *dspl)
MPI_Comm nrnmpi_world_comm
static void nrnmpi_wait(void **)
int nrnmpi_bgp_single_advance(NRNMPI_Spike *)
void * hoc_Emalloc(size_t size)