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() {
102 #if nrn_spikebuf_size > 0
103 make_spikebuf_type();
107 #if nrn_spikebuf_size == 0
110 for (
i = 1;
i < np; ++
i) {
125 MPI_Allgather(spbufout_, 1, spikebuf_type, spbufin_, 1, spikebuf_type,
nrnmpi_comm);
127 n = spbufin_[0].nspike;
134 for (
i = 1;
i < np; ++
i) {
136 n1 = spbufin_[
i].nspike;
178 int nrnmpi_spike_exchange_compressed() {
179 int i, novfl,
n, ntot, idx, bs, bstot;
197 for (
i = 0;
i < np; ++
i) {
218 sizeof(
unsigned char));
241 double nrnmpi_mindelay(
double m) {
261 #define ALLTOALLV_SPARSE_TAG 101980
265 static int MPI_Alltoallv_sparse(
void* sendbuf,
268 MPI_Datatype sendtype,
272 MPI_Datatype recvtype,
277 status = MPI_Comm_rank(comm, &myrank);
279 status = MPI_Comm_size(comm, &nranks);
283 for (rankp = 0; nranks > (1 << rankp); rankp++)
287 ptrdiff_t send_elsize;
288 ptrdiff_t recv_elsize;
290 status = MPI_Type_get_extent(sendtype, &lb, &send_elsize);
292 status = MPI_Type_get_extent(recvtype, &lb, &recv_elsize);
295 MPI_Request* requests = (MPI_Request*)
hoc_Emalloc(nranks * 2 *
sizeof(MPI_Request));
302 for (ngrp = 0; ngrp < (1 << rankp); ngrp++) {
303 int target = myrank ^ ngrp;
305 if (target >= nranks)
307 if (recvcnts[target] == 0)
309 status = MPI_Irecv((
static_cast<char*
>(recvbuf)) + recv_elsize * rdispls[target],
313 ALLTOALLV_SPARSE_TAG,
315 &requests[n_requests++]);
319 status = MPI_Barrier(comm);
322 for (ngrp = 0; ngrp < (1 << rankp); ngrp++) {
323 int target = myrank ^ ngrp;
324 if (target >= nranks)
326 if (sendcnts[target] == 0)
328 status = MPI_Isend((
static_cast<char*
>(sendbuf)) + send_elsize * sdispls[target],
332 ALLTOALLV_SPARSE_TAG,
334 &requests[n_requests++]);
338 status = MPI_Waitall(n_requests, requests, MPI_STATUSES_IGNORE);
342 status = MPI_Barrier(comm);
349 extern void nrnmpi_dbl_alltoallv_sparse(
double* s,
355 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_DOUBLE, r, rcnt, rdispl, MPI_DOUBLE,
nrnmpi_comm);
357 extern void nrnmpi_int_alltoallv_sparse(
int* s,
363 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_INT, r, rcnt, rdispl, MPI_INT,
nrnmpi_comm);
366 extern void nrnmpi_long_alltoallv_sparse(int64_t* s,
372 MPI_Alltoallv_sparse(s, scnt, sdispl, MPI_INT64_T, r, rcnt, rdispl, MPI_INT64_T,
nrnmpi_comm);
376 extern void nrnmpi_int_gather(
int* s,
int* r,
int cnt,
int root) {
380 extern void nrnmpi_int_gatherv(
int* s,
int scnt,
int* r,
int* rcnt,
int* rdispl,
int root) {
381 MPI_Gatherv(s, scnt, MPI_INT, r, rcnt, rdispl, MPI_INT,
root,
nrnmpi_comm);
384 extern void nrnmpi_char_gatherv(
char* s,
int scnt,
char* r,
int* rcnt,
int* rdispl,
int root) {
385 MPI_Gatherv(s, scnt, MPI_CHAR, r, rcnt, rdispl, MPI_CHAR,
root,
nrnmpi_comm);
388 extern void nrnmpi_int_scatter(
int* s,
int* r,
int cnt,
int root) {
392 extern void nrnmpi_char_scatterv(
char* s,
int* scnt,
int* sdispl,
char* r,
int rcnt,
int root) {
393 MPI_Scatterv(s, scnt, sdispl, MPI_CHAR, r, rcnt, MPI_CHAR,
root,
nrnmpi_comm);
396 extern void nrnmpi_int_alltoall(
int* s,
int* r,
int n) {
400 extern void nrnmpi_int_alltoallv(
int* s,
int* scnt,
int* sdispl,
int* r,
int* rcnt,
int* rdispl) {
401 MPI_Alltoallv(s, scnt, sdispl, MPI_INT, r, rcnt, rdispl, MPI_INT,
nrnmpi_comm);
404 extern void nrnmpi_long_alltoallv(int64_t* s,
410 MPI_Alltoallv(s, scnt, sdispl, MPI_INT64_T, r, rcnt, rdispl, MPI_INT64_T,
nrnmpi_comm);
419 MPI_Alltoallv(s, scnt, sdispl, MPI_DOUBLE, r, rcnt, rdispl, MPI_DOUBLE,
nrnmpi_comm);
422 extern void nrnmpi_char_alltoallv(
char* s,
428 MPI_Alltoallv(s, scnt, sdispl, MPI_CHAR, r, rcnt, rdispl, MPI_CHAR,
nrnmpi_comm);
437 void nrnmpi_int_allgather_inplace(
int* srcdest,
int n) {
438 MPI_Allgather(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
n, MPI_INT,
nrnmpi_comm);
445 void nrnmpi_int_allgatherv_inplace(
int* srcdest,
int*
n,
int* dspl) {
446 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
n, dspl, MPI_INT,
nrnmpi_comm);
449 void nrnmpi_char_allgatherv(
char* s,
char* r,
int*
n,
int* dspl) {
453 void nrnmpi_long_allgatherv(int64_t* s, int64_t* r,
int*
n,
int* dspl) {
457 void nrnmpi_long_allgatherv_inplace(
long* srcdest,
int*
n,
int* dspl) {
458 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
n, dspl, MPI_LONG,
nrnmpi_comm);
465 void nrnmpi_dbl_allgatherv_inplace(
double* srcdest,
int*
n,
int* dspl) {
466 MPI_Allgatherv(MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, srcdest,
n, dspl, MPI_DOUBLE,
nrnmpi_comm);
481 void nrnmpi_char_broadcast_world(
char** pstr,
int root) {
483 sz = *pstr ? (strlen(*pstr) + 1) : 0;
491 *pstr =
static_cast<char*
>(
hoc_Emalloc(sz *
sizeof(
char)));
500 int nrnmpi_int_sum_reduce(
int in) {
506 void nrnmpi_assert_opstep(
int opstep,
double t) {
512 buf[0] = (double) opstep;
515 if (opstep != (
int)
buf[0] ||
t !=
buf[1]) {
522 double nrnmpi_dbl_allmin(
double x) {
531 static void pgvts_op(
double* in,
double* inout,
int* len, MPI_Datatype* dptr) {
533 assert(*dptr == MPI_DOUBLE);
535 if (in[0] < inout[0]) {
538 }
else if (in[0] == inout[0]) {
540 if (in[1] < inout[1]) {
543 }
else if (in[1] == inout[1]) {
545 if (in[2] < inout[2]) {
548 }
else if (in[2] == inout[2]) {
550 if (in[3] < inout[3]) {
558 for (
i = 0;
i < 4; ++
i) {
564 int nrnmpi_pgvts_least(
double*
t,
int* op,
int*
init) {
566 double ibuf[4], obuf[4];
568 ibuf[1] = (double) (*op);
569 ibuf[2] = (double) (*
init);
571 for (
i = 0;
i < 4; ++
i) {
574 MPI_Allreduce(ibuf, obuf, 4, MPI_DOUBLE, mpi_pgvts_op,
nrnmpi_comm);
577 assert((
int) obuf[1] <= *op);
578 if ((
int) obuf[1] == *op) {
580 if ((
int) obuf[2] == *
init) {
587 *
init = (int) obuf[2];
599 void nrnmpi_recv_doubles(
double* pd,
int cnt,
int src,
int tag) {
605 MPI_Irecv(pd,
cnt, MPI_DOUBLE, src, tag,
nrnmpi_comm, (MPI_Request*) request);
610 MPI_Wait((MPI_Request*) request, &
status);
620 double nrnmpi_dbl_allreduce(
double x,
int type) {
628 }
else if (
type == 2) {
637 extern "C" void nrnmpi_dbl_allreduce_vec(
double* src,
double* dest,
int cnt,
int type) {
642 for (
i = 0;
i <
cnt; ++
i) {
649 }
else if (
type == 2) {
663 for (
i = 0;
i <
cnt; ++
i) {
670 }
else if (
type == 2) {
679 void nrnmpi_long_allreduce_vec(
long* src,
long* dest,
int cnt,
int type) {
684 for (
i = 0;
i <
cnt; ++
i) {
691 }
else if (
type == 2) {
700 void nrnmpi_dbl_allgather(
double* s,
double* r,
int n) {
701 MPI_Allgather(s,
n, MPI_DOUBLE, r,
n, MPI_DOUBLE,
nrnmpi_comm);
706 static MPI_Comm bgp_comm;
718 for (
i = 0;
i <
n; ++
i) {
719 MPI_Isend(spk, 1, spike_type, hosts[
i], 1, bgp_comm, &r);
720 MPI_Request_free(&r);
727 MPI_Iprobe(MPI_ANY_SOURCE, 1, bgp_comm, &flag, &
status);
729 MPI_Recv(spk, 1, spike_type, MPI_ANY_SOURCE, 1, bgp_comm, &
status);
737 tcnts[0] = nsend - nrecv;
738 MPI_Allreduce(tcnts, tcnts + 1, 1, MPI_INT, MPI_SUM, bgp_comm);
static void nrnmpi_int_alltoallv(int *s, int *scnt, int *sdispl, int *r, int *rcnt, int *rdispl)
static void nrnmpi_dbl_alltoallv(double *s, int *scnt, int *sdispl, double *r, int *rcnt, int *rdispl)
static void nrnmpi_dbl_allgatherv(double *s, double *r, int *n, int *dspl)
static void nrnmpi_int_allgather(int *s, int *r, int n)
static void nrnmpi_barrier()
static void nrnmpi_int_allgatherv(int *s, int *r, int *n, int *dspl)
static int nrnmpi_int_allmax(int x)
void nrnmpi_bgp_multisend(NRNMPI_Spike *, int, int *)
int nrnmpi_bgp_conserve(int nsend, int nrecv)
int nrnmpi_bgp_single_advance(NRNMPI_Spike *)
void hoc_execerror(const char *, const char *)
void nrnbbs_context_wait()
unsigned char * spfixout_
unsigned char * spfixin_ovfl_
#define nrn_spikebuf_size
static void nrnmpi_postrecv_doubles(double *, int, int, int, void **)
static void nrnmpi_wait(void **)
static void nrnmpi_send_doubles(double *, int, int, int)
int const size_t const size_t n
MPI_Comm nrnmpi_world_comm
void * hoc_Emalloc(size_t size)
static void nrnmpi_dbl_broadcast(double *, int, int)
static void nrnmpi_char_broadcast(char *, int, int)
static void nrnmpi_int_broadcast(int *, int, int)