1 #include <../../nrnconf.h>
9 #include <nrnmpi_dynam.h>
26 #define guard(f) nrn_assert(f == MPI_SUCCESS)
31 if (_i != MPI_SUCCESS) { \
32 printf("%s %d\n", #f, _i); \
38 #define nrnmpidebugleak 0
41 extern MPI_Comm nrn_bbs_comm;
44 static int nrnmpi_bufcnt_;
55 #define my_MPI_DOUBLE 1
57 #define my_MPI_PACKED 3
58 #define my_MPI_PICKLE 4
60 static MPI_Datatype mytypes[] = {MPI_INT, MPI_DOUBLE, MPI_CHAR, MPI_PACKED, MPI_CHAR};
62 static void unpack(
void*
buf,
int count,
int my_datatype, bbsmpibuf* r,
const char* errmes) {
66 printf(
"%d unpack upkpos=%d pkposition=%d keypos=%d size=%d\n",
73 assert(r->upkpos >= 0 && r->size >= r->upkpos);
74 guard(MPI_Unpack(r->buf, r->size, &r->upkpos,
type, 2, MPI_INT, nrn_bbs_comm));
76 printf(
"%d unpack r=%p size=%d upkpos=%d type[0]=%d datatype=%d type[1]=%d count=%d\n",
86 if (
type[0] != my_datatype ||
type[1] != count) {
87 printf(
"%d unpack size=%d upkpos=%d type[0]=%d datatype=%d type[1]=%d count=%d\n",
98 guard(MPI_Unpack(r->buf, r->size, &r->upkpos,
buf, count, mytypes[my_datatype], nrn_bbs_comm));
101 void nrnmpi_upkbegin(bbsmpibuf* r) {
105 printf(
"%d nrnmpi_upkbegin %p (preunpack upkpos=%d keypos=%d)\n",
111 assert(r && r->buf && r->size > 0);
113 hoc_execerror(
"subworld process with nhost > 0 cannot use",
"the bulletin board");
116 guard(MPI_Unpack(r->buf, r->size, &r->upkpos, &
p, 1, MPI_INT, nrn_bbs_comm));
121 guard(MPI_Unpack(r->buf, r->size, &
p, &
type, 1, MPI_INT, nrn_bbs_comm));
129 char* nrnmpi_getkey(bbsmpibuf* r) {
133 r->upkpos = r->keypos;
137 s = nrnmpi_upkstr(r);
138 assert(r->pkposition == 0 || r->pkposition == r->upkpos);
139 r->pkposition = r->upkpos;
142 printf(
"getkey return %s\n", s);
147 int nrnmpi_getid(bbsmpibuf* r) {
150 r->upkpos = r->keypos;
154 i = nrnmpi_upkint(r);
157 printf(
"getid return %d\n",
i);
162 int nrnmpi_upkint(bbsmpibuf* r) {
164 unpack(&
i, 1, my_MPI_INT, r,
"upkint");
168 double nrnmpi_upkdouble(bbsmpibuf* r) {
170 unpack(&x, 1, my_MPI_DOUBLE, r,
"upkdouble");
174 void nrnmpi_upkvec(
int n,
double* x, bbsmpibuf* r) {
175 unpack(x,
n, my_MPI_DOUBLE, r,
"upkvec");
178 #if NRNMPI_DYNAMICLOAD
183 char* (*p_cxx_char_alloc)(
int len);
186 char* nrnmpi_upkstr(bbsmpibuf* r) {
189 unpack(&len, 1, my_MPI_INT, r,
"upkstr length");
190 #if NRNMPI_DYNAMICLOAD
191 s = (*p_cxx_char_alloc)(len + 1);
195 unpack(s, len, my_MPI_CHAR, r,
"upkstr string");
200 char* nrnmpi_upkpickle(
size_t* size, bbsmpibuf* r) {
203 unpack(&len, 1, my_MPI_INT, r,
"upkpickle length");
205 #if NRNMPI_DYNAMICLOAD
206 s = (*p_cxx_char_alloc)(len + 1);
210 unpack(s, len, my_MPI_PICKLE, r,
"upkpickle data");
214 static void resize(bbsmpibuf* r,
int size) {
216 if (r->size < size) {
217 newsize = (size / 64) * 64 + 128;
218 r->buf =
static_cast<char*
>(
hoc_Erealloc(r->buf, newsize));
224 void nrnmpi_pkbegin(bbsmpibuf* r) {
227 hoc_execerror(
"subworld process with nhost > 0 cannot use",
"the bulletin board");
233 "%d nrnmpi_pkbegin %p size=%d pkposition=%d\n",
nrnmpi_myid_bbs, r, r->size, r->pkposition);
235 guard(MPI_Pack(&
type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
238 void nrnmpi_enddata(bbsmpibuf* r) {
239 int p,
type, isize, oldsize;
245 guard(MPI_Pack_size(1, MPI_INT, nrn_bbs_comm, &isize));
247 resize(r, r->pkposition + isize);
249 if (oldsize < r->pkposition + isize) {
253 guard(MPI_Pack(&
type, 1, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
255 printf(
"%d nrnmpi_enddata buf=%p size=%d pkposition=%d\n",
261 guard(MPI_Pack(&
p, 1, MPI_INT, r->buf, r->size, &
type, nrn_bbs_comm));
263 printf(
"%d after nrnmpi_enddata, %d was packed at beginning and 0 was packed before %d\n",
270 static void pack(
void* inbuf,
int incount,
int my_datatype, bbsmpibuf* r,
const char*
e) {
272 int dsize, isize, oldsize;
274 printf(
"%d pack %p count=%d type=%d outbuf-%p pkposition=%d %s\n",
283 guard(MPI_Pack_size(incount, mytypes[my_datatype], nrn_bbs_comm, &dsize));
284 guard(MPI_Pack_size(2, MPI_INT, nrn_bbs_comm, &isize));
286 resize(r, r->pkposition + dsize + isize);
288 if (oldsize < r->pkposition + dsize + isize) {
289 printf(
"%d %p need %d more. end up with total of %d\n",
296 type[0] = my_datatype;
298 guard(MPI_Pack(
type, 2, MPI_INT, r->buf, r->size, &r->pkposition, nrn_bbs_comm));
300 inbuf, incount, mytypes[my_datatype], r->buf, r->size, &r->pkposition, nrn_bbs_comm));
306 void nrnmpi_pkint(
int i, bbsmpibuf* r) {
309 pack(&ii, 1, my_MPI_INT, r,
"pkint");
312 void nrnmpi_pkdouble(
double x, bbsmpibuf* r) {
315 pack(&xx, 1, my_MPI_DOUBLE, r,
"pkdouble");
318 void nrnmpi_pkvec(
int n,
double* x, bbsmpibuf* r) {
319 pack(x,
n, my_MPI_DOUBLE, r,
"pkvec");
322 void nrnmpi_pkstr(
const char* s, bbsmpibuf* r) {
325 pack(&len, 1, my_MPI_INT, r,
"pkstr length");
326 pack((
char*) s, len, my_MPI_CHAR, r,
"pkstr string");
329 void nrnmpi_pkpickle(
const char* s,
size_t size, bbsmpibuf* r) {
331 pack(&len, 1, my_MPI_INT, r,
"pkpickle length");
332 pack((
char*) s, len, my_MPI_PICKLE, r,
"pkpickle data");
335 void nrnmpi_bbssend(
int dest,
int tag, bbsmpibuf* r) {
337 printf(
"%d nrnmpi_bbssend %p dest=%d tag=%d size=%d\n",
349 int save_position = r->pkposition;
350 int save_upkpos = r->upkpos;
353 r->pkposition = r->upkpos;
354 nrnmpi_pkint(tag, r);
355 r->pkposition = save_position;
356 r->upkpos = save_upkpos;
361 assert(r->buf && r->keypos <= r->size);
362 guard(MPI_Send(r->buf, r->size, MPI_PACKED, dest, tag, nrn_bbs_comm));
364 guard(MPI_Send(
NULL, 0, MPI_PACKED, dest, tag, nrn_bbs_comm));
372 int nrnmpi_bbsrecv(
int source, bbsmpibuf* r) {
376 source = MPI_ANY_SOURCE;
381 guard(MPI_Probe(source, MPI_ANY_TAG, nrn_bbs_comm, &
status));
382 guard(MPI_Get_count(&
status, MPI_PACKED, &size));
384 printf(
"%d nrnmpi_bbsrecv probe size=%d source=%d tag=%d\n",
391 guard(MPI_Recv(r->buf, r->size, MPI_PACKED, source, MPI_ANY_TAG, nrn_bbs_comm, &
status));
399 if (
status.MPI_TAG == 20) {
401 int save_upkpos = r->upkpos;
404 tag = nrnmpi_upkint(r);
405 r->upkpos = save_upkpos;
411 int nrnmpi_bbssendrecv(
int dest,
int tag, bbsmpibuf* s, bbsmpibuf* r) {
412 int size, itag, source;
418 if (!nrnmpi_iprobe(&size, &itag, &source) || source != dest) {
422 nrnmpi_bbssend(dest, tag, s);
424 return nrnmpi_bbsrecv(dest, r);
427 int nrnmpi_iprobe(
int* size,
int* tag,
int* source) {
430 guard(MPI_Iprobe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &flag, &
status));
433 *source =
status.MPI_SOURCE;
437 guard(MPI_Get_count(&
status, MPI_PACKED, size));
442 void nrnmpi_probe(
int* size,
int* tag,
int* source) {
445 guard(MPI_Probe(MPI_ANY_SOURCE, MPI_ANY_TAG, nrn_bbs_comm, &
status));
447 *source =
status.MPI_SOURCE;
451 guard(MPI_Get_count(&
status, MPI_PACKED, size));
454 bbsmpibuf* nrnmpi_newbuf(
int size) {
461 buf->buf = (
char*) 0;
477 void nrnmpi_copy(bbsmpibuf* dest, bbsmpibuf* src) {
480 for (
i = 0;
i < src->size; ++
i) {
481 dest->buf[
i] = src->buf[
i];
483 dest->pkposition = src->pkposition;
484 dest->upkpos = src->upkpos;
485 dest->keypos = src->keypos;
488 static void nrnmpi_free(bbsmpibuf*
buf) {
501 void nrnmpi_ref(bbsmpibuf*
buf) {
506 void nrnmpi_unref(bbsmpibuf*
buf) {
509 if (
buf->refcount <= 0) {
516 void nrnmpi_checkbufleak() {
517 if (nrnmpi_bufcnt_ > 0) {
void hoc_execerror(const char *, const char *)
char * cxx_char_alloc(size_t sz)
int const size_t const size_t n
void * hoc_Erealloc(void *buf, size_t size)
void * hoc_Emalloc(size_t size)
static double resize(void *v)
static double pack(void *v)
static double unpack(void *v)