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 
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 
40 void hoc_parallel_begin(void) {
41 #if !OCSMALL
42  Symbol *sym;
43  double first, last;
44  char *method;
45  int i, j;
46 
47 
48  last = xpop();
49  first = xpop();
50  sym = spop();
51  pushs(sym);
52 
53  method = getenv("NEURON_PARALLEL_METHOD");
54  if (!method) {
55  pushx(first);
56  pushx(last);
57  return;
58  }
59  if (parallel_seen++) {
60  hoc_warning("Only one parallel loop per batch run allowed.",
61  "This loop is being executed serially");
62  pushx(first);
63  pushx(last);
64  return;
65  }
66 
67  if (!parallel_sub) { /* if 0 then master */
68  /* the master instance executes the following portion of the loop */
69  for (i = ((int) first) + 1; i <= (int) last; i++) {
70  char buf[10], *pnt = parallel_argv;
71 
72  /* increment pnt to "00000" */
73  for (j = 0; j < 2; j++) {
74  /*EMPTY*/
75  while (*pnt++);
76  }
77 
78  /* replace "00000" with actual value */
79  sprintf(buf, "%5d", i);
80  strcpy(pnt, buf);
81 
82  /* farm-out all but the first instance of the loop */
83 #if LINDA
84  /* place arguments for eval() into tuple space, Linda
85  doesn't seem to want to let the fxn in an eval take
86  arrays as args */
87  __linda_out("parallel sargs", sargv, senvp);
88  __linda_out("parallel args", parallel_argv:sargv, parallel_envp:senvp);
89  __linda_eval("parallel run", parallel_hoc_main(i), i);
90 #endif
91  }
92 
93 #if LINDA
94  /* do first pass though loop on master node (first to first) */
95  pushx(first);
96  pushx(first);
97 #else
98  /* run in serial if not LINDA */
99  pushx(first);
100  pushx(last);
101 #endif
102 
103  /* block until all instances of loop have finished */
104 #if LINDA
105  i = (int)last - (int)first;
106  while (i-- > 0) {
107  int err_val, err_num;
108 
109  __linda_in("parallel run", ?err_val, ?err_num);
110  /* could test err_val != 0 but currently will always equal 0 */
111  }
112 #endif
113 
114  /* assign value of symbol to last+1 as would be upon exiting a serial loop */
115  if (!ISARRAY(sym)) {
116  if (sym->subtype == USERDOUBLE) {
117  pval = sym->u.pval;
118  } else {
119  pval = OPVAL(sym);
120  }
121  } else {
122  if (sym->subtype == USERDOUBLE) {
123  pval = sym->u.pval + araypt(sym, SYMBOL);
124  } else {
125  pval = OPVAL(sym) + araypt(sym, OBJECTVAR);
126  }
127  }
128  end_val = last + 1;
129 
130  } else {
131  /* the subsidiary instances do remaining contiguous blocks of the loop */
132 
133  /* only do "parallel_val" pass though loop */
134  pushx((double) parallel_val);
135  pushx((double) parallel_val);
136 
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  _largc = j;
191 
192  pnt = tenvp;
193  for (j = 0; *pnt; j++) {
194  _lenvp[j] = pnt;
195  /*EMPTY*/
196  while (*pnt++);
197  }
198 
199  /* run is killed at end of parallel for-loop (hoc_parallel_end()) */
200  hoc_main1(_largc, _largv, _lenvp);
201 #endif
202  return 0;
203 }
204 
205 void save_parallel_argv(int argc, const char** argv) {
206  /* first arg is program, save 2 & 3 for -parallel flags */
207 #if !defined(WIN32)
208  const char *pnt;
209  int j;
210 
211  /* count how long the block of memory should be */
212  for (j = 0; j < argc && (strcmp(argv[j], "-") != 0); j++) {
213  pnt = argv[j];
214  while (*pnt++) { sargv++; }
215  sargv++; /* add room for '\0' */
216  }
217  sargv += 16; /* add 10 for "-parallel" and 6 for val ("00000") */
218 
219  /* need room for extra '\0' at end, each space is of size (char) */
220  sargv = (sargv + 1) * sizeof(char);
221 
222  /* malloc blocks of memory */
223  parallel_argv = static_cast<char*>(emalloc(sargv));
224 
225 #if 0
226  /* place the strings into the memory block separated by '\0' */
227  strcpy((pnt = parallel_argv), argv[0]);
228  /*EMPTY*/
229  while (*pnt++);
230  strcpy(pnt, "-parallel 0"); /* pad val with 00000 (assume max int) */
231  pnt += 16;
232  for (j = 1; j < argc && (strcmp(argv[j], "-") != 0); j++) {
233  if (strcmp(argv[j], "-parallel") == 0) {
234  /* if sub-process then get val, increment past "-parallel" and "val" */
235  parallel_sub = 1;
236  parallel_val = atoi(argv[++j]);
237 
238  } else {
239  strcpy(pnt, argv[j]);
240  /*EMPTY*/
241  while (*pnt++);
242  }
243  }
244  *pnt = '\0'; /* place extra '\0' at end */
245 #endif
246 #endif
247 }
248 
249 void save_parallel_envp(void) {
250 #if LINDA
251 #if !defined(__APPLE__)
252  extern char** environ;
253  char** envp = environ;
254 #endif
255 #if defined(__APPLE__)
256  char** envp = (*_NSGetEnviron());
257 #endif
258  char *pnt;
259  int j;
260  char** envp = environ;
261 
262  /* count how long the block of memory should be */
263  for (j = 0; envp[j]; j++) {
264  pnt = envp[j];
265  while (*pnt++) { senvp++; }
266  senvp++; /* add room for '\0' */
267  }
268 
269  /* need room for extra '\0' at end, each space is of size (char) */
270  senvp = (senvp + 1) * sizeof(char);
271 
272  /* malloc blocks of memory */
273  parallel_envp = static_cast<char *>(emalloc(senvp));
274 
275  /* place the strings into the memory block separated by '\0' */
276  pnt = parallel_envp;
277  for (j = 0; envp[j]; j++) {
278  strcpy(pnt, envp[j]);
279  /*EMPTY*/
280  while (*pnt++);
281  }
282  *pnt = '\0'; /* place extra '\0' at end */
283 #endif
284 }
void hoc_final_exit()
Definition: hoc.cpp:1130
static double end_val
Definition: parallel.cpp:22
int parallel_sub
Definition: parallel.cpp:30
void pushx(double d)
Definition: code.cpp:641
int parallel_val
Definition: parallel.cpp:31
static int parallel_seen
Definition: parallel.cpp:19
void save_parallel_envp(void)
Definition: parallel.cpp:249
int araypt(Symbol *sp, int type)
Definition: code.cpp:2402
static int first
Definition: fmenu.cpp:186
#define Fprintf
Definition: model.h:249
#define SYMBOL
Definition: model.h:102
sprintf(buf," if (secondorder) {\ " int _i;\" " for(_i=0;_i< %d;++_i) {\" " _p[_slist%d[_i]]+=dt *_p[_dlist%d[_i]];\" " }}\", numeqn, listnum, listnum)
static int senvp
Definition: parallel.cpp:27
static double * pval
Definition: parallel.cpp:21
void pushs(Symbol *d)
Definition: code.cpp:708
Symbol * spop(void)
Definition: code.cpp:835
static char * parallel_argv
Definition: parallel.cpp:25
int
Definition: nrnmusic.cpp:71
void hoc_warning(const char *, const char *)
void hoc_parallel_end(void)
Definition: parallel.cpp:141
#define ISARRAY(arg)
Definition: hocdec.h:163
void hoc_parallel_begin(void)
Definition: parallel.cpp:40
int parallel_hoc_main(int i)
Definition: parallel.cpp:160
double * pval
Definition: hocdec.h:136
char * getenv(const char *s)
Definition: macprt.cpp:67
size_t j
#define USERDOUBLE
Definition: hocdec.h:93
Definition: model.h:57
char * name
Definition: init.cpp:16
double xpop(void)
Definition: code.cpp:777
char * emalloc(unsigned n)
Definition: list.cpp:189
#define NUM_ARGS
Definition: parallel.cpp:24
#define OPVAL(sym)
Definition: hocdec.h:304
long subtype
Definition: model.h:59
static char * parallel_envp
Definition: parallel.cpp:26
static int sargv
Definition: parallel.cpp:27
#define i
Definition: md1redef.h:12
char buf[512]
Definition: init.cpp:13
int hoc_main1(int, const char **, const char **)
Definition: hoc.cpp:972
static int argc
Definition: inithoc.cpp:53
union Symbol::@18 u
static char ** argv
Definition: inithoc.cpp:54
void save_parallel_argv(int argc, const char **argv)
Definition: parallel.cpp:205