1 #include <../../nrnconf.h>
9 #include <nrnmpi_dynam.h>
19 #include <nrnmpidec.h>
23 #define nrn_mpi_assert(arg) nrn_assert(arg == MPI_SUCCESS)
25 #define nrnmpidebugleak 0
31 static int nrnmpi_bufcnt_;
42 #define my_MPI_DOUBLE 1
44 #define my_MPI_PACKED 3
45 #define my_MPI_PICKLE 4
47 static MPI_Datatype mytypes[] = {MPI_INT, MPI_DOUBLE, MPI_CHAR, MPI_PACKED, MPI_CHAR};
49 static void unpack(
void*
buf,
int count,
int my_datatype, bbsmpibuf* r,
const char* errmes) {
53 printf(
"%d unpack upkpos=%d pkposition=%d keypos=%d size=%d\n",
60 assert(r->upkpos >= 0 && r->size >= r->upkpos);
61 nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &r->upkpos,
type, 2, MPI_INT, nrn_bbs_comm));
63 printf(
"%d unpack r=%p size=%d upkpos=%d type[0]=%d datatype=%d type[1]=%d count=%d\n",
73 if (
type[0] != my_datatype ||
type[1] != count) {
74 printf(
"%d unpack size=%d upkpos=%d type[0]=%d datatype=%d type[1]=%d count=%d\n",
86 MPI_Unpack(r->buf, r->size, &r->upkpos,
buf, count, mytypes[my_datatype], nrn_bbs_comm));
89 void nrnmpi_upkbegin(bbsmpibuf* r) {
93 printf(
"%d nrnmpi_upkbegin %p (preunpack upkpos=%d keypos=%d)\n",
99 assert(r && r->buf && r->size > 0);
101 hoc_execerror(
"subworld process with nhost > 0 cannot use",
"the bulletin board");
104 nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &r->upkpos, &
p, 1, MPI_INT, nrn_bbs_comm));
109 nrn_mpi_assert(MPI_Unpack(r->buf, r->size, &
p, &
type, 1, MPI_INT, nrn_bbs_comm));
117 char* nrnmpi_getkey(bbsmpibuf* r) {
121 r->upkpos = r->keypos;
125 s = nrnmpi_upkstr(r);
126 assert(r->pkposition == 0 || r->pkposition == r->upkpos);
127 r->pkposition = r->upkpos;
130 printf(
"getkey return %s\n",
s);
135 int nrnmpi_getid(bbsmpibuf* r) {
138 r->upkpos = r->keypos;
142 i = nrnmpi_upkint(r);
145 printf(
"getid return %d\n",
i);
150 int nrnmpi_upkint(bbsmpibuf* r) {
152 unpack(&
i, 1, my_MPI_INT, r,
"upkint");
156 double nrnmpi_upkdouble(bbsmpibuf* r) {
158 unpack(&x, 1, my_MPI_DOUBLE, r,
"upkdouble");
162 void nrnmpi_upkvec(
int n,
double* x, bbsmpibuf* r) {
163 unpack(x,
n, my_MPI_DOUBLE, r,
"upkvec");
166 #if NRNMPI_DYNAMICLOAD
171 char* (*p_cxx_char_alloc)(
int len);
174 char* nrnmpi_upkstr(bbsmpibuf* r) {
177 unpack(&len, 1, my_MPI_INT, r,
"upkstr length");
178 #if NRNMPI_DYNAMICLOAD
179 s = (*p_cxx_char_alloc)(len + 1);
183 unpack(
s, len, my_MPI_CHAR, r,
"upkstr string");
188 char* nrnmpi_upkpickle(
size_t* size, bbsmpibuf* r) {
191 unpack(&len, 1, my_MPI_INT, r,
"upkpickle length");
193 #if NRNMPI_DYNAMICLOAD
194 s = (*p_cxx_char_alloc)(len + 1);
198 unpack(
s, len, my_MPI_PICKLE, r,
"upkpickle data");
202 static void resize(bbsmpibuf* r,
int size) {
204 if (r->size < size) {
205 newsize = (size / 64) * 64 + 128;
206 r->buf =
static_cast<char*
>(
hoc_Erealloc(r->buf, newsize));
212 void nrnmpi_pkbegin(bbsmpibuf* r) {
215 hoc_execerror(
"subworld process with nhost > 0 cannot use",
"the bulletin board");
221 "%d nrnmpi_pkbegin %p size=%d pkposition=%d\n",
nrnmpi_myid_bbs, r, r->size, r->pkposition);
223 nrn_mpi_assert(MPI_Pack(&
type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
226 void nrnmpi_enddata(bbsmpibuf* r) {
232 int oldsize = r->size;
234 nrn_mpi_assert(MPI_Pack_size(1, MPI_INT, nrn_bbs_comm, &isize));
235 resize(r, r->pkposition + isize);
237 if (oldsize < r->pkposition + isize) {
241 nrn_mpi_assert(MPI_Pack(&
type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
243 printf(
"%d nrnmpi_enddata buf=%p size=%d pkposition=%d\n",
249 nrn_mpi_assert(MPI_Pack(&
p, 1, MPI_INT, r->buf, r->size, &
type, nrn_bbs_comm));
251 printf(
"%d after nrnmpi_enddata, %d was packed at beginning and 0 was packed before %d\n",
258 static void pack(
void* inbuf,
int incount,
int my_datatype, bbsmpibuf* r,
const char* e) {
262 int oldsize = r->size;
263 printf(
"%d pack %p count=%d type=%d outbuf-%p pkposition=%d %s\n",
272 nrn_mpi_assert(MPI_Pack_size(incount, mytypes[my_datatype], nrn_bbs_comm, &dsize));
273 nrn_mpi_assert(MPI_Pack_size(2, MPI_INT, nrn_bbs_comm, &isize));
274 resize(r, r->pkposition + dsize + isize);
276 if (oldsize < r->pkposition + dsize + isize) {
277 printf(
"%d %p need %d more. end up with total of %d\n",
284 type[0] = my_datatype;
286 nrn_mpi_assert(MPI_Pack(
type, 2, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
287 nrn_mpi_assert(MPI_Pack(
288 inbuf, incount, mytypes[my_datatype], r->buf, r->size, &r->pkposition, nrn_bbs_comm));
294 void nrnmpi_pkint(
int i, bbsmpibuf* r) {
297 pack(&
ii, 1, my_MPI_INT, r,
"pkint");
300 void nrnmpi_pkdouble(
double x, bbsmpibuf* r) {
303 pack(&xx, 1, my_MPI_DOUBLE, r,
"pkdouble");
306 void nrnmpi_pkvec(
int n,
double* x, bbsmpibuf* r) {
307 pack(x,
n, my_MPI_DOUBLE, r,
"pkvec");
310 void nrnmpi_pkstr(
const char*
s, bbsmpibuf* r) {
313 pack(&len, 1, my_MPI_INT, r,
"pkstr length");
314 pack((
char*)
s, len, my_MPI_CHAR, r,
"pkstr string");
317 void nrnmpi_pkpickle(
const char*
s,
size_t size, bbsmpibuf* r) {
319 pack(&len, 1, my_MPI_INT, r,
"pkpickle length");
320 pack((
char*)
s, len, my_MPI_PICKLE, r,
"pkpickle data");
323 void nrnmpi_bbssend(
int dest,
int tag, bbsmpibuf* r) {
325 printf(
"%d nrnmpi_bbssend %p dest=%d tag=%d size=%d\n",
337 int save_position = r->pkposition;
338 int save_upkpos = r->upkpos;
341 r->pkposition = r->upkpos;
342 nrnmpi_pkint(tag, r);
343 r->pkposition = save_position;
344 r->upkpos = save_upkpos;
349 assert(r->buf && r->keypos <= r->size);
350 nrn_mpi_assert(MPI_Send(r->buf, r->size, MPI_PACKED, dest, tag, nrn_bbs_comm));
352 nrn_mpi_assert(MPI_Send(
nullptr, 0, MPI_PACKED, dest, tag, nrn_bbs_comm));
360 int nrnmpi_bbsrecv(
int source, bbsmpibuf* r) {
364 source = MPI_ANY_SOURCE;
369 nrn_mpi_assert(MPI_Probe(source, MPI_ANY_TAG, nrn_bbs_comm, &
status));
370 nrn_mpi_assert(MPI_Get_count(&
status, MPI_PACKED, &size));
372 printf(
"%d nrnmpi_bbsrecv probe size=%d source=%d tag=%d\n",
380 MPI_Recv(r->buf, r->size, MPI_PACKED, source, MPI_ANY_TAG, nrn_bbs_comm, &
status));
388 if (
status.MPI_TAG == 20) {
390 int save_upkpos = r->upkpos;
393 tag = nrnmpi_upkint(r);
394 r->upkpos = save_upkpos;
400 int nrnmpi_bbssendrecv(
int dest,
int tag, bbsmpibuf*
s, bbsmpibuf* r) {
401 int size, itag, source;
405 if (!nrnmpi_iprobe(&size, &itag, &source) || source != dest) {
409 nrnmpi_bbssend(dest, tag,
s);
411 return nrnmpi_bbsrecv(dest, r);
414 int nrnmpi_iprobe(
int* size,
int* tag,
int* source) {
417 nrn_mpi_assert(MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &flag, &
status));
420 *source =
status.MPI_SOURCE;
424 nrn_mpi_assert(MPI_Get_count(&
status, MPI_PACKED, size));
429 void nrnmpi_probe(
int* size,
int* tag,
int* source) {
431 nrn_mpi_assert(MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &
status));
433 *source =
status.MPI_SOURCE;
437 nrn_mpi_assert(MPI_Get_count(&
status, MPI_PACKED, size));
440 bbsmpibuf* nrnmpi_newbuf(
int size) {
447 buf->buf = (
char*) 0;
463 void nrnmpi_copy(bbsmpibuf* dest, bbsmpibuf* src) {
466 for (
i = 0;
i < src->size; ++
i) {
467 dest->buf[
i] = src->buf[
i];
469 dest->pkposition = src->pkposition;
470 dest->upkpos = src->upkpos;
471 dest->keypos = src->keypos;
474 static void nrnmpi_free(bbsmpibuf*
buf) {
487 void nrnmpi_ref(bbsmpibuf*
buf) {
492 void nrnmpi_unref(bbsmpibuf*
buf) {
495 if (
buf->refcount <= 0) {
502 void nrnmpi_checkbufleak() {
503 if (nrnmpi_bufcnt_ > 0) {
char * cxx_char_alloc(size_t sz)
void hoc_execerror(const char *s1, const char *s2)
void * hoc_Emalloc(size_t)
int const size_t const size_t n
void * hoc_Erealloc(void *ptr, std::size_t size)
static double pack(void *v)
static double unpack(void *v)
static double resize(void *v)