NEURON
parallel.cpp
Go to the documentation of this file.
1 #include <../../nrnconf.h>
2 /* /local/src/master/nrn/src/oc/parallel.cpp,v 1.5 1997/03/13 14:18:17 hines Exp */
3 #if MAC
4 #define OCSMALL 1
5 #define WIN32 1
6 #endif
7 
8 #if !OCSMALL
9 #include <stdlib.h>
10 #if HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #if defined(__APPLE__)
14 #include <crt_externs.h>
15 #endif
16 #include "hoc.h"
17 #include "parse.hpp" /* OBJECTVAR */
18 
19 static int parallel_seen;
20 
21 static double* pval; /* pointer to loop counter value */
22 static double end_val; /* value to assign loop counter upon completion of loop */
23 
24 #define NUM_ARGS 256
25 static char* parallel_argv;
26 static char* parallel_envp;
27 static int sargv = 0, senvp = 0;
28 #endif /*!OCSMALL*/
29 
30 int parallel_sub = 0;
31 int parallel_val; /* for use with parallel neuron (see hoc.cpp) */
32 
33 /*
34  stack has final, initial, symbol
35  and should contain these on exit in order to execute the following shortfor
36 */
37 
38 
39 void hoc_parallel_begin(void) {
40 #if !OCSMALL
41  Symbol* sym;
42  double first, last;
43  char* method;
44  int i, j;
45 
46 
47  last = xpop();
48  first = xpop();
49  sym = spop();
50  pushs(sym);
51 
52  method = getenv("NEURON_PARALLEL_METHOD");
53  if (!method) {
54  pushx(first);
55  pushx(last);
56  return;
57  }
58  if (parallel_seen++) {
59  hoc_warning("Only one parallel loop per batch run allowed.",
60  "This loop is being executed serially");
61  pushx(first);
62  pushx(last);
63  return;
64  }
65 
66  if (!parallel_sub) { /* if 0 then master */
67  /* the master instance executes the following portion of the loop */
68  for (i = ((int) first) + 1; i <= (int) last; i++) {
69  // parallel_argv will be null on windows, which triggers an ICE in
70  // some cases, see #1840.
71  if (parallel_argv) {
72  char buf[10], *pnt = parallel_argv;
73  /* increment pnt to "00000" */
74  for (j = 0; j < 2; j++) {
75  /*EMPTY*/
76  while (*pnt++)
77  ;
78  }
79  /* replace "00000" with actual value */
80  sprintf(buf, "%5d", i);
81  strcpy(pnt, buf);
82  }
83  /* farm-out all but the first instance of the loop */
84 #if LINDA
85  /* place arguments for eval() into tuple space, Linda
86  doesn't seem to want to let the fxn in an eval take
87  arrays as args */
88  __linda_out("parallel sargs", sargv, senvp);
89  __linda_out("parallel args", parallel_argv : sargv, parallel_envp : senvp);
90  __linda_eval("parallel run", parallel_hoc_main(i), i);
91 #endif
92  }
93 
94 #if LINDA
95  /* do first pass though loop on master node (first to first) */
96  pushx(first);
97  pushx(first);
98 #else
99  /* run in serial if not LINDA */
100  pushx(first);
101  pushx(last);
102 #endif
103 
104  /* block until all instances of loop have finished */
105 #if LINDA
106  i = (int) last - (int) first;
107  while (i-- > 0) {
108  int err_val, err_num;
109 
110  __linda_in("parallel run", ?err_val, ?err_num);
111  /* could test err_val != 0 but currently will always equal 0 */
112  }
113 #endif
114 
115  /* assign value of symbol to last+1 as would be upon exiting a serial loop */
116  if (!ISARRAY(sym)) {
117  if (sym->subtype == USERDOUBLE) {
118  pval = sym->u.pval;
119  } else {
120  pval = OPVAL(sym);
121  }
122  } else {
123  if (sym->subtype == USERDOUBLE) {
124  pval = sym->u.pval + araypt(sym, SYMBOL);
125  } else {
126  pval = OPVAL(sym) + araypt(sym, OBJECTVAR);
127  }
128  }
129  end_val = last + 1;
130 
131  } else {
132  /* the subsidiary instances do remaining contiguous blocks of the loop */
133 
134  /* only do "parallel_val" pass though loop */
135  pushx((double) parallel_val);
136  pushx((double) parallel_val);
137  }
138 #endif
139 }
140 
141 void hoc_parallel_end(void) {
142 #if !OCSMALL
143  /* need to exit after for-loop for all sub-processes */
144  if (parallel_sub) {
145  hoc_final_exit();
146 #if LINDA
147  lexit(0);
148 #else
149  exit(0);
150 #endif
151 
152  } else {
153  /* assign loop counter the proper end value */
154  *pval = end_val;
155  }
156 #endif
157 }
158 
159 
161 #if !OCSMALL
162  /*ARGSUSED*/
163  const char **_largv, **_lenvp;
164  const char* pnt;
165  char *targv, *tenvp;
166  int j, _largc;
167  _largv = static_cast<const char**>(emalloc(NUM_ARGS * sizeof(char*)));
168  _lenvp = static_cast<const char**>(emalloc(NUM_ARGS * sizeof(char*)));
169 #if LINDA
170  char name[20];
171 
172  gethostname(name, 20);
173  Fprintf(stderr, "\nLaunching sub-process on %s.\n\t1\n", name);
174 
175  __linda_in("parallel sargs", ?sargv, ?senvp);
176 #endif
177  targv = static_cast<char*>(emalloc(sargv));
178  tenvp = static_cast<char*>(emalloc(senvp));
179  /* pointers need to point to memory that will be filled by __linda_in() */
180 #if LINDA
181  __linda_in("parallel args", ? targv :, ? tenvp :);
182 #endif
183 
184  pnt = targv;
185  for (j = 0; *pnt; j++) {
186  _largv[j] = pnt;
187  /*EMPTY*/
188  while (*pnt++)
189  ;
190  }
191  _largc = j;
192 
193  pnt = tenvp;
194  for (j = 0; *pnt; j++) {
195  _lenvp[j] = pnt;
196  /*EMPTY*/
197  while (*pnt++)
198  ;
199  }
200 
201  /* run is killed at end of parallel for-loop (hoc_parallel_end()) */
202  hoc_main1(_largc, _largv, _lenvp);
203 #endif
204  return 0;
205 }
206 
207 void save_parallel_argv(int argc, const char** argv) {
208  /* first arg is program, save 2 & 3 for -parallel flags */
209 #if !defined(WIN32)
210  const char* pnt;
211  int j;
212 
213  /* count how long the block of memory should be */
214  for (j = 0; j < argc && (strcmp(argv[j], "-") != 0); j++) {
215  pnt = argv[j];
216  while (*pnt++) {
217  sargv++;
218  }
219  sargv++; /* add room for '\0' */
220  }
221  sargv += 16; /* add 10 for "-parallel" and 6 for val ("00000") */
222 
223  /* need room for extra '\0' at end, each space is of size (char) */
224  sargv = (sargv + 1) * sizeof(char);
225 
226  /* malloc blocks of memory */
227  parallel_argv = static_cast<char*>(emalloc(sargv));
228 
229 #if 0
230  /* place the strings into the memory block separated by '\0' */
231  strcpy((pnt = parallel_argv), argv[0]);
232  /*EMPTY*/
233  while (*pnt++);
234  strcpy(pnt, "-parallel 0"); /* pad val with 00000 (assume max int) */
235  pnt += 16;
236  for (j = 1; j < argc && (strcmp(argv[j], "-") != 0); j++) {
237  if (strcmp(argv[j], "-parallel") == 0) {
238  /* if sub-process then get val, increment past "-parallel" and "val" */
239  parallel_sub = 1;
240  parallel_val = atoi(argv[++j]);
241 
242  } else {
243  strcpy(pnt, argv[j]);
244  /*EMPTY*/
245  while (*pnt++);
246  }
247  }
248  *pnt = '\0'; /* place extra '\0' at end */
249 #endif
250 #endif
251 }
252 
253 void save_parallel_envp(void) {
254 #if LINDA
255 #if !defined(__APPLE__)
256  extern char** environ;
257  char** envp = environ;
258 #endif
259 #if defined(__APPLE__)
260  char** envp = (*_NSGetEnviron());
261 #endif
262  char* pnt;
263  int j;
264  char** envp = environ;
265 
266  /* count how long the block of memory should be */
267  for (j = 0; envp[j]; j++) {
268  pnt = envp[j];
269  while (*pnt++) {
270  senvp++;
271  }
272  senvp++; /* add room for '\0' */
273  }
274 
275  /* need room for extra '\0' at end, each space is of size (char) */
276  senvp = (senvp + 1) * sizeof(char);
277 
278  /* malloc blocks of memory */
279  parallel_envp = static_cast<char*>(emalloc(senvp));
280 
281  /* place the strings into the memory block separated by '\0' */
282  pnt = parallel_envp;
283  for (j = 0; envp[j]; j++) {
284  strcpy(pnt, envp[j]);
285  /*EMPTY*/
286  while (*pnt++)
287  ;
288  }
289  *pnt = '\0'; /* place extra '\0' at end */
290 #endif
291 }
double xpop(void)
Definition: code.cpp:788
void pushx(double d)
Definition: code.cpp:658
void pushs(Symbol *d)
Definition: code.cpp:721
Symbol * spop(void)
Definition: code.cpp:846
int araypt(Symbol *sp, int type)
Definition: code.cpp:2416
sprintf(buf, " if (secondorder) {\n" " int _i;\n" " for (_i = 0; _i < %d; ++_i) {\n" " _p[_slist%d[_i]] += dt*_p[_dlist%d[_i]];\n" " }}\n", numeqn, listnum, listnum)
static int first
Definition: fmenu.cpp:190
char buf[512]
Definition: init.cpp:13
void save_parallel_argv(int argc, const char **argv)
Definition: parallel.cpp:207
void save_parallel_envp(void)
Definition: parallel.cpp:253
void hoc_warning(const char *, const char *)
#define ISARRAY(arg)
Definition: hocdec.h:164
#define USERDOUBLE
Definition: hocdec.h:93
#define OPVAL(sym)
Definition: hocdec.h:306
static int argc
Definition: inithoc.cpp:53
static char ** argv
Definition: inithoc.cpp:54
void hoc_final_exit()
Definition: hoc.cpp:1131
int hoc_main1(int, const char **, const char **)
Definition: hoc.cpp:983
char * getenv(const char *s)
Definition: macprt.cpp:67
#define i
Definition: md1redef.h:12
#define SYMBOL
Definition: model.h:102
#define Fprintf
Definition: model.h:234
char * name
Definition: init.cpp:16
char * emalloc(unsigned n)
Definition: list.cpp:166
size_t j
static double end_val
Definition: parallel.cpp:22
int parallel_hoc_main(int i)
Definition: parallel.cpp:160
static int parallel_seen
Definition: parallel.cpp:19
static int senvp
Definition: parallel.cpp:27
static char * parallel_envp
Definition: parallel.cpp:26
static double * pval
Definition: parallel.cpp:21
int parallel_val
Definition: parallel.cpp:31
void hoc_parallel_end(void)
Definition: parallel.cpp:141
int parallel_sub
Definition: parallel.cpp:30
void hoc_parallel_begin(void)
Definition: parallel.cpp:39
static int sargv
Definition: parallel.cpp:27
#define NUM_ARGS
Definition: parallel.cpp:24
static char * parallel_argv
Definition: parallel.cpp:25
Definition: model.h:57
long subtype
Definition: model.h:59
union Symbol::@18 u
double * pval
Definition: hocdec.h:137