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