NEURON
bbsdirectmpi.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 #include <nrnmpi.h>
3 #include "bbsconf.h"
4 #ifdef NRNMPI // to end of file
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <unistd.h>
8 #include <InterViews/resource.h>
9 #include "oc2iv.h"
10 #include "bbs.h"
11 #include "bbsdirect.h"
12 #include "bbssrv2mpi.h"
13 #include "bbssrv.h"
14 
15 extern void nrnmpi_int_broadcast(int*, int, int);
16 
17 #if defined(HAVE_STL)
18 #if defined(HAVE_SSTREAM) // the standard ...
19 #include <map>
20 #else
21 #include <pair.h>
22 #include <map.h>
23 #endif
24 
25 #define debug 0
26 
27 struct ltint {
28  bool operator() (int i, int j) const {
29  return i < j;
30  }
31 };
32 
33 class KeepArgs : public std::map<int, bbsmpibuf*, ltint>{};
34 
35 #endif
36 
37 
41  }
42  sendbuf_ = nil;
43  recvbuf_ = nil;
45 #if defined(HAVE_STL)
46  keepargs_ = new KeepArgs();
47 #endif
48 }
49 
51  nrnmpi_unref(sendbuf_);
52  nrnmpi_unref(recvbuf_);
53 #if defined(HAVE_STL)
54  delete keepargs_;
55 #endif
56 }
57 
58 void BBSDirect::perror(const char* s) {
59  printf("BBSDirect error %s\n", s);
60 }
61 
62 void BBSDirect::context() {
64  nrnmpi_enddata(sendbuf_);
66 
67  // if nhost > 1 of the id_bbs==0 subworld,
68  // then id > 0 need to execute the context statement
69  // but id == 0 does not.
71  size_t n;
72  bbsmpibuf* rsav = recvbuf_; // May naturally be NULL anyway
73  recvbuf_ = nrnmpi_newbuf(sendbuf_->size);
74  nrnmpi_ref(recvbuf_);
75  nrnmpi_copy(recvbuf_, sendbuf_);
76  nrnmpi_upkbegin(recvbuf_);
77  nrnmpi_upkint(recvbuf_);
78  nrnmpi_upkint(recvbuf_); // slot reserved for tag
79  execute_helper(&n, -1, false);
80  nrnmpi_unref(recvbuf_);
81  recvbuf_ = rsav;
82  }
83 
84  nrnmpi_unref(sendbuf_);
85  sendbuf_ = nil;
86 }
87 
88 int BBSDirect::upkint() {
89  int i;
90  i = nrnmpi_upkint(recvbuf_);
91 #if debug
92  printf("upkint returning %d\n", i);
93 #endif
94  return i;
95 }
96 
97 double BBSDirect::upkdouble() {
98  double x;
99  x = nrnmpi_upkdouble(recvbuf_);
100 #if debug
101  printf("upkdouble returning %g\n", x);
102 #endif
103  return x;
104 }
105 
106 void BBSDirect::upkvec(int n, double* x) {
107  nrnmpi_upkvec(n, x, recvbuf_);
108 }
109 
110 char* BBSDirect::upkstr() {
111  char* s;
112  s = nrnmpi_upkstr(recvbuf_);
113 #if debug
114  printf("upkstr returning |%s|\n", s);
115 #endif
116  return s;
117 }
118 
119 char* BBSDirect::upkpickle(size_t* n) {
120  char* s;
121  s = nrnmpi_upkpickle(n, recvbuf_);
122 #if debug
123  printf("upkpickle returning %d bytes\n", *n);
124 #endif
125  return s;
126 }
127 
128 void BBSDirect::pkbegin() {
129 #if debug
130 printf("%d BBSDirect::pkbegin\n", nrnmpi_myid_bbs);
131 #endif
132  nrnmpi_unref(sendbuf_);
133  sendbuf_ = nrnmpi_newbuf(100);
134  nrnmpi_ref(sendbuf_);
135  nrnmpi_pkbegin(sendbuf_);
136 }
137 
138 void BBSDirect::pkint(int i) {
139 #if debug
140 printf("%d BBSDirect::pkint %d\n", nrnmpi_myid_bbs, i);
141 #endif
142  nrnmpi_pkint(i, sendbuf_);
143 }
144 
145 void BBSDirect::pkdouble(double x) {
146 #if debug
147 printf("%d BBSDirect::pkdouble\n", nrnmpi_myid_bbs, x);
148 #endif
149  nrnmpi_pkdouble(x, sendbuf_);
150 }
151 
152 void BBSDirect::pkvec(int n, double* x) {
153 #if debug
154 printf("%d BBSDirect::pkvec n=%d\n", nrnmpi_myid_bbs, n);
155 #endif
156  nrnmpi_pkvec(n, x, sendbuf_);
157 }
158 
159 void BBSDirect::pkstr(const char* s) {
160 #if debug
161 printf("%d BBSDirect::pkstr %s\n", nrnmpi_myid_bbs, s);
162 #endif
163  nrnmpi_pkstr(s, sendbuf_);
164 }
165 
166 void BBSDirect::pkpickle(const char* s, size_t n) {
167 #if debug
168 printf("%d BBSDirect::pkpickle %d bytes\n", nrnmpi_myid_bbs, n);
169 #endif
170  nrnmpi_pkpickle(s, n, sendbuf_);
171 }
172 
173 void BBSDirect::post(const char* key) {
174 #if debug
175  printf("%d BBSDirect::post |%s|\n", nrnmpi_myid_bbs, key);
176 #endif
177  nrnmpi_enddata(sendbuf_);
178  nrnmpi_pkstr(key, sendbuf_);
179  BBSDirectServer::server_->post(key, sendbuf_);
180  nrnmpi_unref(sendbuf_);
181  sendbuf_ = nil;
183 }
184 
185 void BBSDirect::post_todo(int parentid) {
186 #if debug
187  printf("%d BBSDirect::post_todo for %d\n", nrnmpi_myid_bbs, parentid);
188 #endif
189  nrnmpi_enddata(sendbuf_);
190  nrnmpi_pkint(parentid, sendbuf_);
191  BBSDirectServer::server_->post_todo(parentid, nrnmpi_myid_bbs, sendbuf_);
192  nrnmpi_unref(sendbuf_);
193  sendbuf_ = nil;
195 }
196 
197 void BBSDirect::post_result(int id) {
198 #if debug
199  printf("%d BBSDirect::post_result %d\n", nrnmpi_myid_bbs, id);
200 #endif
201  nrnmpi_enddata(sendbuf_);
202  nrnmpi_pkint(id, sendbuf_);
203  BBSDirectServer::server_->post_result(id, sendbuf_);
204  nrnmpi_unref(sendbuf_);
205  sendbuf_ = nil;
207 }
208 
211  int id = BBSDirectServer::server_->look_take_todo(&recvbuf_);
212  if (id) {
213  nrnmpi_upkbegin(recvbuf_);
214 
215 #if debug
216 printf("%d look_take_todo getid=%d\n", nrnmpi_getid(recvbuf_));
217 #endif
218  }
219 #if debug
220 printf("%d BBSDirect::look_take_todo id=%d\n", nrnmpi_myid_bbs, id);
221 #endif
222  return id;
223 }
224 
225 int BBSDirect::take_todo() {
226  int id = BBSDirectServer::server_->look_take_todo(&recvbuf_);
227  if (id == 0) {
228  printf("BBSDirect::take_todo blocking\n");
229  assert(0);
230  }
231 #if debug
232  printf("%d BBSDirect::take_todo id=%d\n", nrnmpi_myid_bbs, id);
233 #endif
234  return id;
235 }
236 
237 int BBSDirect::look_take_result(int pid) {
239  int id = BBSDirectServer::server_->look_take_result(pid, &recvbuf_);
240 #if debug
241  printf("%d BBSDirect::look_take_result id=%d pid=%d\n", nrnmpi_myid_bbs, id, pid);
242 #endif
243  if (id) {
244  nrnmpi_upkbegin(recvbuf_);
245  }
246 #if debug
247 printf("%d look_take_result return id=%d\n", nrnmpi_myid_bbs, id);
248 #endif
249  return id;
250 }
251 
252 int BBSDirect::master_take_result(int pid) {
253  assert(is_master());
255  for (;;) {
256  int id = look_take_result(pid);
257  if (id) {
258  return id;
259  }
260  // wait for a message (no MPI_Iprobe)
262  }
263 }
264 
265 void BBSDirect::save_args(int userid) {
266 #if defined(HAVE_STL)
267  nrnmpi_ref(sendbuf_);
268  keepargs_->insert(
269  std::pair<const int, bbsmpibuf*>(userid, sendbuf_)
270  );
271 
272 #endif
273  post_todo(working_id_);
274 }
275 
276 void BBSDirect::return_args(int userid) {
277 #if defined(HAVE_STL)
278  KeepArgs::iterator i = keepargs_->find(userid);
279  nrnmpi_unref(recvbuf_);
280  recvbuf_ = nil;
281  if (i != keepargs_->end()) {
282  recvbuf_ = (*i).second;
283  keepargs_->erase(i);
284  nrnmpi_upkbegin(recvbuf_);
285  BBSImpl::return_args(userid);
286  }
287 #endif
288 }
289 
290 bool BBSDirect::look_take(const char* key) {
292  bool b = BBSDirectServer::server_->look_take(key, &recvbuf_);
293  if (b) {
294  nrnmpi_upkbegin(recvbuf_);
295  }
296 #if debug
297  if (b) {
298  printf("look_take |%s| true\n", key);
299  }else{
300  printf("look_take |%s| false\n", key);
301  }
302 #endif
303  return b;
304 }
305 
306 bool BBSDirect::look(const char* key) {
308  bool b = BBSDirectServer::server_->look(key, &recvbuf_);
309  if (b) {
310  nrnmpi_upkbegin(recvbuf_);
311  }
312 #if debug
313  printf("look |%s| %d\n", key, b);
314 #endif
315  return b;
316 }
317 
318 void BBSDirect::take(const char* key) { // blocking
319  int id;
320  double st = time();
321  for (;;) {
322  if (look_take(key)) {
323  wait_time_ += time() - st;
324  return;
325  } else if (!master_works_) {
327  } else if ((id = look_take_todo()) != 0) {
328  wait_time_ += time() - st;
329  execute(id);
330  st = time();
331  }else{
332  // perhaps should do something meaningful here
333  // like check whether to quit or not
334  }
335  }
336 }
337 
338 void BBSDirect::done() {
339 //printf("%d bbsdirect::done\n", nrnmpi_myid_world);
340  int i;
341  if (done_) {
342  return;
343  }
345  int info[2]; info[0] = -2; info[1] = -1;
346 //printf("%d broadcast %d %d\n", nrnmpi_myid_world, info[0], info[1]);
347  nrnmpi_int_broadcast(info, 2, 0);
348  }
349  BBSImpl::done();
350  done_ = true;
351  nrnmpi_unref(sendbuf_);
352  sendbuf_ = nrnmpi_newbuf(20);
353 #if debug
354 printf("done: numprocs_bbs=%d\n", nrnmpi_numprocs_bbs);
355 #endif
356  for (i=1; i < nrnmpi_numprocs_bbs; ++i) {
357  nrnmpi_bbssend(i, QUIT, sendbuf_);
358 //printf("kill %d\n", i);
359  }
361 }
362 
363 void BBSDirect::start() {
364  if (started_) { return; }
365  BBSImpl::start();
366  is_master_ = true;
368  bbs_handle();
369 }
370 
371 #endif //NRNMPI
static double userid(void *v)
Definition: ocbbs.cpp:225
virtual void perror(const char *)
#define assert(ex)
Definition: hocassrt.h:26
void post(const char *key)
static double look_take(void *v)
Definition: ocbbs.cpp:468
virtual double upkdouble()
static void handle()
bool look_take(const char *key)
void execute(Inst *p)
Definition: code.cpp:2651
virtual void return_args(int)
virtual void done()
Definition: bbs.cpp:484
int nrnmpi_numprocs_world
bool look(const char *key)
int nrnmpi_myid_bbs
virtual void post_todo(int parentid)
virtual void pkdouble(double)
virtual void start()
Definition: bbs.cpp:500
virtual int upkint()
int nrnmpi_numprocs_bbs
virtual void post(const char *)
static BBSDirectServer * server_
Definition: bbslsrv2.h:18
void context(int ncid, int *cids)
virtual void done()
static List * info
static void handle_block()
static double map(void *v)
Definition: mlinedit.cpp:46
virtual bool look_take(const char *)
int const size_t const size_t n
Definition: nrngsl.h:12
virtual char * upkstr()
int nrnmpi_numprocs
_CONST char * s
Definition: system.cpp:74
virtual int look_take_todo()
static void nrnmpi_int_broadcast(int *, int, int)
Definition: ocbbs.cpp:60
virtual void return_args(int userid)
Definition: ocbbs.cpp:1308
virtual void upkvec(int, double *)
#define printf
Definition: mwprefix.h:26
virtual void save_args(int)
#define key
Definition: spt2queue.cpp:20
size_t j
#define nil
Definition: enter-scope.h:36
virtual void pkint(int)
virtual void pkstr(const char *)
virtual void start()
virtual void pkbegin()
virtual int take_todo()
void post_result(int id)
virtual int look_take_result(int pid)
virtual bool look(const char *)
int look_take_result(int parentid)
#define i
Definition: md1redef.h:12
#define id
Definition: md1redef.h:33
virtual int master_take_result(int pid)
virtual char * upkpickle(size_t *)
virtual ~BBSDirect()
virtual void context()
virtual void take(const char *)
void bbs_handle()
Definition: datapath.cpp:29
virtual void pkpickle(const char *, size_t)
void post_todo(int parentid, int cid)
#define QUIT
Definition: bbssrv.h:4
virtual void post_result(int id)
virtual void pkvec(int, double *)