NEURON
bbsclimpi.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 <errno.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #ifdef HAVE_UNISTD_H
8 #include <unistd.h>
9 #endif
10 #include <InterViews/resource.h>
11 #include "nrnpy.h"
12 #include "oc2iv.h"
13 #include "bbs.h"
14 #include "bbsrcli.h"
15 #include "bbssrv.h"
16 
17 extern void nrnmpi_int_broadcast(int*, int, int);
18 
19 #define debug 0
20 
21 #include <map>
22 
23 class KeepArgs: public std::map<int, bbsmpibuf*> {};
24 
25 int BBSClient::sid_;
26 
28  sendbuf_ = nullptr;
29  recvbuf_ = nullptr;
30  request_ = nrnmpi_newbuf(100);
31  nrnmpi_ref(request_);
32  keepargs_ = new KeepArgs();
34 }
35 
37  nrnmpi_unref(sendbuf_);
38  nrnmpi_unref(recvbuf_);
39  nrnmpi_unref(request_);
40  delete keepargs_;
41 }
42 
43 void BBSClient::perror(const char* s) {
44  printf("BBSClient error: %s\n", s);
45 }
46 
47 void BBSClient::upkbegin() {
48  nrnmpi_upkbegin(recvbuf_);
49 }
50 
51 char* BBSClient::getkey() {
52  return nrnmpi_getkey(recvbuf_);
53 }
54 
55 int BBSClient::getid() {
56  return nrnmpi_getid(recvbuf_);
57 }
58 
59 int BBSClient::upkint() {
60  return nrnmpi_upkint(recvbuf_);
61 }
62 
63 double BBSClient::upkdouble() {
64  return nrnmpi_upkdouble(recvbuf_);
65 }
66 
67 void BBSClient::upkvec(int n, double* x) {
68  nrnmpi_upkvec(n, x, recvbuf_);
69 }
70 
71 char* BBSClient::upkstr() {
72  return nrnmpi_upkstr(recvbuf_); // do not forget to free(string)
73 }
74 
75 std::vector<char> BBSClient::upkpickle() {
76  std::size_t len{};
77  char* s = nrnmpi_upkpickle(&len, recvbuf_);
78  std::vector<char> ret(s, s + len);
79  delete[] s;
80  return ret;
81 }
82 
83 void BBSClient::pkbegin() {
84  if (!sendbuf_) {
85  sendbuf_ = nrnmpi_newbuf(100);
86  nrnmpi_ref(sendbuf_);
87  }
88  nrnmpi_pkbegin(sendbuf_);
89 }
90 
91 void BBSClient::pkint(int i) {
92  nrnmpi_pkint(i, sendbuf_);
93 }
94 
95 void BBSClient::pkdouble(double x) {
96  nrnmpi_pkdouble(x, sendbuf_);
97 }
98 
99 void BBSClient::pkvec(int n, double* x) {
100  nrnmpi_pkvec(n, x, sendbuf_);
101 }
102 
103 void BBSClient::pkstr(const char* s) {
104  nrnmpi_pkstr(s, sendbuf_);
105 }
106 
107 void BBSClient::pkpickle(const std::vector<char>& s) {
108  nrnmpi_pkpickle(s.data(), s.size(), sendbuf_);
109 }
110 
111 void BBSClient::post(const char* key) {
112 #if debug
113  printf("%d BBSClient::post |%s|\n", nrnmpi_myid_bbs, key);
114  fflush(stdout);
115 #endif
116  nrnmpi_enddata(sendbuf_);
117  nrnmpi_pkstr(key, sendbuf_);
118  nrnmpi_bbssend(sid_, POST, sendbuf_);
119  nrnmpi_unref(sendbuf_);
120  sendbuf_ = nullptr;
121 }
122 
123 void BBSClient::post_todo(int parentid) {
124 #if debug
125  printf("%d BBSClient::post_todo for %d\n", nrnmpi_myid_bbs, parentid);
126  fflush(stdout);
127 #endif
128  nrnmpi_enddata(sendbuf_);
129  nrnmpi_pkint(parentid, sendbuf_);
130  nrnmpi_bbssend(sid_, POST_TODO, sendbuf_);
131  nrnmpi_unref(sendbuf_);
132  sendbuf_ = nullptr;
133 }
134 
135 void BBSClient::post_result(int id) {
136 #if debug
137  printf("%d BBSClient::post_result %d\n", nrnmpi_myid_bbs, id);
138  fflush(stdout);
139 #endif
140  nrnmpi_enddata(sendbuf_);
141  nrnmpi_pkint(id, sendbuf_);
142  nrnmpi_bbssend(sid_, POST_RESULT, sendbuf_);
143  nrnmpi_unref(sendbuf_);
144  sendbuf_ = nullptr;
145 }
146 
147 int BBSClient::get(const char* key, int type) {
148 #if debug
149  printf("%d BBSClient::get |%s| type=%d\n", nrnmpi_myid_bbs, key, type);
150  fflush(stdout);
151 #endif
152  nrnmpi_pkbegin(request_);
153  nrnmpi_enddata(request_);
154  nrnmpi_pkstr(key, request_);
155  return get(type);
156 }
157 
158 int BBSClient::get(int key, int type) {
159 #if debug
160  printf("%d BBSClient::get %d type=%d\n", nrnmpi_myid_bbs, key, type);
161  fflush(stdout);
162 #endif
163  nrnmpi_pkbegin(request_);
164  nrnmpi_enddata(request_);
165  nrnmpi_pkint(key, request_);
166  return get(type) - 1; // sent id+1 so cannot be mistaken for QUIT
167 }
168 
169 int BBSClient::get(int type) { // blocking
170  fflush(stdout);
171  fflush(stderr);
172  double ts = time();
173  nrnmpi_unref(recvbuf_);
174  recvbuf_ = nrnmpi_newbuf(100);
175  nrnmpi_ref(recvbuf_);
176  int msgtag = nrnmpi_bbssendrecv(sid_, type, request_, recvbuf_);
177  errno = 0;
178  wait_time_ += time() - ts;
179 #if debug
180  printf("%d BBSClient::get return msgtag=%d\n", nrnmpi_myid_bbs, msgtag);
181  fflush(stdout);
182 #endif
183  if (msgtag == QUIT) {
184  done();
185  }
186  return msgtag;
187 }
188 
189 bool BBSClient::look_take(const char* key) {
190 #if debug
191  printf("%d BBSClient::look_take %s\n", nrnmpi_myid_bbs, key);
192 #endif
193  int type = get(key, LOOK_TAKE);
194  bool b = (type == LOOK_TAKE_YES);
195  if (b) {
196  upkbegin();
197  }
198  return b;
199 }
200 
201 bool BBSClient::look(const char* key) {
202 #if debug
203  printf("%d BBSClient::look %s\n", nrnmpi_myid_bbs, key);
204 #endif
205  int type = get(key, LOOK);
206  bool b = (type == LOOK_YES);
207  if (b) {
208  upkbegin();
209  }
210  return b;
211 }
212 
213 void BBSClient::take(const char* key) { // blocking
214  get(key, TAKE);
215  upkbegin();
216 }
217 
219  int type = get(0, LOOK_TAKE_TODO);
220  if (type) {
221  upkbegin();
222  }
223  return type;
224 }
225 
226 int BBSClient::take_todo() {
227  int type;
228  while ((type = get(0, TAKE_TODO)) == CONTEXT) {
229  upkbegin();
230  upkint(); // throw away userid
231  upkint(); // throw away info in reserved second slot for worker_id
232 #if debug
233  printf("%d execute context\n", nrnmpi_myid_bbs);
234  fflush(stdout);
235 #endif
236  execute_helper(-1);
237  }
238  upkbegin();
239  return type;
240 }
241 
242 int BBSClient::look_take_result(int pid) {
243  int type = get(pid, LOOK_TAKE_RESULT);
244  if (type) {
245  upkbegin();
246  }
247  return type;
248 }
249 
250 void BBSClient::save_args(int userid) {
251  nrnmpi_ref(sendbuf_);
252  keepargs_->emplace(userid, sendbuf_);
254 }
255 
256 void BBSClient::return_args(int userid) {
257  KeepArgs::iterator i = keepargs_->find(userid);
258  nrnmpi_unref(recvbuf_);
259  recvbuf_ = nullptr;
260  if (i != keepargs_->end()) {
261  recvbuf_ = (*i).second;
262  nrnmpi_ref(recvbuf_);
263  keepargs_->erase(i);
264  upkbegin();
266  }
267 }
268 
269 void BBSClient::done() {
270 #if defined(USE_PYTHON)
271  extern void (*p_nrnpython_finalize)();
272 #endif
273 #if debug
274  printf("%d BBSClient::done\n", nrnmpi_myid_bbs);
275  fflush(stdout);
276 #endif
278  if (nrnmpi_myid == 0) {
279  int info[2];
280  info[0] = -2;
281  info[1] = -1;
282  // printf("%d broadcast %d %d\n", nrnmpi_myid_world, info[0], info[1]);
283  nrnmpi_int_broadcast(info, 2, 0);
284  }
285  }
286 #if defined(USE_PYTHON)
287  if (neuron::python::methods.interpreter_start) {
289  }
290 #endif
291  BBSImpl::done();
293 #if defined(USE_PYTHON)
294  if (p_nrnpython_finalize) {
295  (*p_nrnpython_finalize)();
296  }
297 #endif
298  exit(0);
299 }
300 
301 void BBSClient::start() {
302  if (started_) {
303  return;
304  }
305 #if debug
306  printf("%d BBSClient start\n", nrnmpi_myid_bbs);
307  fflush(stdout);
308 #endif
309  BBSImpl::start();
310  sid_ = 0;
311 #if 0
312  { // a worker
313  is_master_ = false;
314  nrnmpi_pkbegin(request_);
315  nrnmpi_enddata(request_);
316  nrn_assert(get(HELLO) == HELLO);
317  return;
318  }
319 #endif
320 }
321 
322 #endif // NRNMPI
#define POST_TODO
Definition: bbssrv.h:13
#define LOOK_TAKE_RESULT
Definition: bbssrv.h:16
#define TAKE
Definition: bbssrv.h:7
#define TAKE_TODO
Definition: bbssrv.h:17
#define LOOK_TAKE
Definition: bbssrv.h:6
#define LOOK
Definition: bbssrv.h:5
#define POST_RESULT
Definition: bbssrv.h:14
#define POST
Definition: bbssrv.h:4
#define HELLO
Definition: bbssrv.h:12
#define QUIT
Definition: bbssrv.h:3
#define LOOK_YES
Definition: bbssrv.h:8
#define LOOK_TAKE_TODO
Definition: bbssrv.h:15
#define CONTEXT
Definition: bbssrv.h:18
#define LOOK_TAKE_YES
Definition: bbssrv.h:10
void pkstr(const char *) override
void return_args(int) override
double upkdouble() override
int upkint() override
std::vector< char > upkpickle() override
int take_todo() override
void post_result(int id) override
bool look(const char *) override
char * upkstr() override
static int sid_
Definition: bbsrcli.h:51
int get(const char *key, int type)
void post_todo(int parentid) override
void pkvec(int, double *) override
void save_args(int) override
~BBSClient() override
void perror(const char *) override
void pkbegin() override
int look_take_result(int pid) override
void pkint(int) override
void done() override
int look_take_todo() override
void start() override
void upkvec(int, double *) override
KeepArgs * keepargs_
Definition: bbsrcli.h:52
void pkpickle(const std::vector< char > &) override
void pkdouble(double) override
void post(const char *) override
void take(const char *) override
bool look_take(const char *) override
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 started_
Definition: bbsimpl.h:61
double wait_time_
Definition: bbsimpl.h:56
virtual double time()
Definition: bbs.cpp:116
virtual void start()
Definition: bbs.cpp:471
virtual void done()
Definition: bbs.cpp:464
#define key
Definition: tqueue.hpp:45
#define i
Definition: md1redef.h:19
void(* p_nrnpython_finalize)()
static double map(void *v)
Definition: mlinedit.cpp:43
printf
Definition: extdef.h:5
impl_ptrs methods
Collection of pointers to functions with python-version-specific implementations.
Definition: nrnpy.cpp:21
static List * info
#define nrn_assert(x)
assert()-like macro, independent of NDEBUG status
Definition: nrn_assert.h:33
int const size_t const size_t n
Definition: nrngsl.h:10
s
Definition: multisend.cpp:521
void nrnmpi_terminate()
Definition: nrnmpi.cpp:184
short type
Definition: cabvars.h:10
int nrnmpi_myid
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
int(* interpreter_start)(int)
Definition: nrnpy.h:43