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
160
int
parallel_hoc_main
(
int
i
) {
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
}
xpop
double xpop(void)
Definition:
code.cpp:788
pushx
void pushx(double d)
Definition:
code.cpp:658
pushs
void pushs(Symbol *d)
Definition:
code.cpp:721
spop
Symbol * spop(void)
Definition:
code.cpp:846
araypt
int araypt(Symbol *sp, int type)
Definition:
code.cpp:2416
sprintf
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)
first
static int first
Definition:
fmenu.cpp:190
buf
char buf[512]
Definition:
init.cpp:13
save_parallel_argv
void save_parallel_argv(int argc, const char **argv)
Definition:
parallel.cpp:207
save_parallel_envp
void save_parallel_envp(void)
Definition:
parallel.cpp:253
hoc_warning
void hoc_warning(const char *, const char *)
hoc.h
ISARRAY
#define ISARRAY(arg)
Definition:
hocdec.h:164
USERDOUBLE
#define USERDOUBLE
Definition:
hocdec.h:93
OPVAL
#define OPVAL(sym)
Definition:
hocdec.h:306
argc
static int argc
Definition:
inithoc.cpp:53
argv
static char ** argv
Definition:
inithoc.cpp:54
hoc_final_exit
void hoc_final_exit()
Definition:
hoc.cpp:1131
hoc_main1
int hoc_main1(int, const char **, const char **)
Definition:
hoc.cpp:983
getenv
char * getenv(const char *s)
Definition:
macprt.cpp:67
i
#define i
Definition:
md1redef.h:12
SYMBOL
#define SYMBOL
Definition:
model.h:102
Fprintf
#define Fprintf
Definition:
model.h:234
name
char * name
Definition:
init.cpp:16
emalloc
char * emalloc(unsigned n)
Definition:
list.cpp:166
j
size_t j
Definition:
nrngsl_real_radix2.cpp:50
end_val
static double end_val
Definition:
parallel.cpp:22
parallel_hoc_main
int parallel_hoc_main(int i)
Definition:
parallel.cpp:160
parallel_seen
static int parallel_seen
Definition:
parallel.cpp:19
senvp
static int senvp
Definition:
parallel.cpp:27
parallel_envp
static char * parallel_envp
Definition:
parallel.cpp:26
pval
static double * pval
Definition:
parallel.cpp:21
parallel_val
int parallel_val
Definition:
parallel.cpp:31
hoc_parallel_end
void hoc_parallel_end(void)
Definition:
parallel.cpp:141
parallel_sub
int parallel_sub
Definition:
parallel.cpp:30
hoc_parallel_begin
void hoc_parallel_begin(void)
Definition:
parallel.cpp:39
sargv
static int sargv
Definition:
parallel.cpp:27
NUM_ARGS
#define NUM_ARGS
Definition:
parallel.cpp:24
parallel_argv
static char * parallel_argv
Definition:
parallel.cpp:25
Symbol
Definition:
model.h:57
Symbol::subtype
long subtype
Definition:
model.h:59
Symbol::u
union Symbol::@18 u
Symbol::pval
double * pval
Definition:
hocdec.h:137
src
oc
parallel.cpp