1 |
#!/bin/bash |
2 |
|
3 |
# Escript/Finley wrapper for python |
4 |
# Sets LD_LIBRARY_PATH and PYTHONPATH and then runs either python or the MPI launcher |
5 |
|
6 |
#Extra paths can be configured about a page further down |
7 |
#Search for EXTRA_PATH="" |
8 |
|
9 |
#set to 1 if performing this is a standalone build and /packages contains the relevant tools |
10 |
STANDALONE=0 |
11 |
|
12 |
#Now we find the location of this script |
13 |
#Note that this location should be absolute but does not need to be unique |
14 |
scriptdir="" |
15 |
CURDIR=`pwd` |
16 |
|
17 |
#Environment vars which control operations: |
18 |
# ESCRIPT_NUM_NODES, ESCRIPT_NUM_PROC, ESCRIPT_NUM_THREADS, ESCRIPT_HOSTFILE, ESCRIPT_CREATESTDFILES |
19 |
|
20 |
HOSTFILE=/tmp/escript.$$ |
21 |
|
22 |
|
23 |
#Need to match if the name contains / |
24 |
if [[ $0 =~ / ]] |
25 |
then |
26 |
# We are not using the PATH to find the script |
27 |
cd `dirname $0` |
28 |
scriptdir=`pwd` |
29 |
cd $CURDIR |
30 |
else |
31 |
# name does not contain / therefore we are using |
32 |
tscriptdir=`which $0` |
33 |
if [ $? != 0 ] |
34 |
then |
35 |
echo "Error unable to determine script directory. Exiting." |
36 |
exit 1 |
37 |
fi |
38 |
scriptdir=`dirname $tscriptdir` |
39 |
fi |
40 |
|
41 |
cd $scriptdir/.. |
42 |
ESCRIPT_ROOT=`pwd` |
43 |
cd .. |
44 |
ESCRIPT_PARENT=`pwd` |
45 |
cd $CURDIR |
46 |
##### End finding ESCRIPT_ROOT ######## |
47 |
|
48 |
PYTHON_MPI="$ESCRIPT_ROOT/lib/pythonMPI" |
49 |
PYTHON_CMD=python |
50 |
|
51 |
# if possible please express paths relative to $ESCRIPT_ROOT unless |
52 |
# they are in an unrelated location |
53 |
|
54 |
EXTRA_DYLD_LIBRARY_PATH="" |
55 |
EXTRA_PATH=$ESCRIPT_ROOT/bin |
56 |
EXTRA_PYTHONPATH=$ESCRIPT_ROOT |
57 |
EXTRA_LD_LIBRARY_PATH=$ESCRIPT_ROOT/lib |
58 |
|
59 |
if [ $STANDALONE == 1 ] |
60 |
then |
61 |
EXTRA_PATH=$ESCRIPT_PARENT/packages/python/bin:$EXTRA_PATH |
62 |
EXTRA_LD_LIBRARY_PATH=$ESCRIPT_PARENT/packages/boost/lib:$ESCRIPT_PARENT/packages/netcdf/lib/:$EXTRA_LD_LIBRARY_PATH |
63 |
EXTRA_LD_LIBRARY_PATH=$ESCRIPT_PARENT/packages/vtk/lib/vtk-5.2:$ESCRIPT_PARENT/packages/mesa/lib:$EXTRA_LD_LIBRARY_PATH |
64 |
EXTRA_LD_LIBRARY_PATH=$ESCRIPT_PARENT/packages/python/lib:$EXTRA_LD_LIBRARY_PATH |
65 |
EXTRA_PYTHONPATH=$ESCRIPT_PARENT/packages/numarray/lib:$ESCRIPT_PARENT/packages/vtk/lib/python2.6/site-packages:$EXTRA_PYTHONPATH |
66 |
fi |
67 |
|
68 |
|
69 |
|
70 |
HELP_TEXT=" |
71 |
Usage: escript [options] script.py [arguments...] |
72 |
-n nn number of nodes to use |
73 |
-p np number of MPI processes to spawn |
74 |
-t nt number of OpenMP threads to use |
75 |
-f file name of MPI hostfile |
76 |
-c print compile information for escript and exit |
77 |
-V print escript version and exit |
78 |
-i interactive mode |
79 |
-b do not invoke python (run non-python programs) |
80 |
-e print export statements for environment and exit |
81 |
-o redirect output from MPI to files |
82 |
-v print diagnostics |
83 |
-x ..reserved for future use .. |
84 |
script.py Your python script |
85 |
arguments... The optional command-line arguments to your script |
86 |
" |
87 |
|
88 |
if [ "$1" = "--help" ]; then |
89 |
echo "$HELP_TEXT" |
90 |
exit 0 |
91 |
fi |
92 |
#======================================================================================= |
93 |
|
94 |
# Avoid bug in hybrid runs with MPT MPI |
95 |
|
96 |
|
97 |
# Parse the command-line options |
98 |
# option e should not be followed by a : |
99 |
while getopts 'bn:p:t:f:h:ecVviox' option |
100 |
do |
101 |
case "$option" in |
102 |
"b") DOBINARY=yes |
103 |
;; |
104 |
"n") ESCRIPT_NUM_NODES=$OPTARG |
105 |
;; |
106 |
"p") ESCRIPT_NUM_PROC=$OPTARG |
107 |
;; |
108 |
"t") ESCRIPT_NUM_THREADS=$OPTARG |
109 |
;; |
110 |
"f") ESCRIPT_HOSTFILE=$OPTARG |
111 |
;; |
112 |
"c") cat $ESCRIPT_ROOT/lib/buildvars |
113 |
exit 0 |
114 |
;; |
115 |
"V") echo "escript-pre2.0(build "`grep svn_revision $ESCRIPT_ROOT/lib/buildvars |cut -d= -f2`")" |
116 |
exit 0 |
117 |
;; |
118 |
"h") echo "$HELPTEXT" |
119 |
exit 0 |
120 |
;; |
121 |
"i") DOINTERACTIVE=yes |
122 |
;; |
123 |
"e") echo "export LD_LIBRARY_PATH=$EXTRA_LD_LIBRARY_PATH:\$LD_LIBRARY_PATH" |
124 |
echo "export PYTHONPATH=$EXTRA_PYTHONPATH:\$PYTHONPATH" |
125 |
echo "export PATH=$EXTRA_PATH:\$PATH" |
126 |
if [ `uname` == Darwin ] |
127 |
then |
128 |
echo "export DYLD_LIBRARY_PATH=$EXTRA_DYLD_LIBRARY_PATH:$EXTRA_LD_LIBRARY_PATH:\$DYLD_LIBRARY_PATH" |
129 |
fi |
130 |
exit 0 |
131 |
;; |
132 |
"o") ESCRIPT_CREATESTDFILES="yes" |
133 |
;; |
134 |
"v") ESCRIPT_VERBOSE="yes" |
135 |
;; |
136 |
"x") echo "-x not implemented yet" |
137 |
exit 1 |
138 |
;; |
139 |
?) echo "$HELP_TEXT" |
140 |
exit 1 |
141 |
;; |
142 |
esac |
143 |
done |
144 |
shift `expr $OPTIND - 1` |
145 |
#============================================== |
146 |
# |
147 |
# Read the MPI_FLAVOUR from the buildvars |
148 |
# |
149 |
MPI_FLAVOUR=`grep mpi_flavour $ESCRIPT_ROOT/lib/buildvars |cut -d= -f2` |
150 |
|
151 |
if [ -f "$ESCRIPT_ROOT/lib/Compiled.with.mpi" ] && [ $MPI_FLAVOUR == "none" ] |
152 |
then |
153 |
echo "compiled with MPI but no MPI flavour specified." |
154 |
exit 1 |
155 |
fi |
156 |
|
157 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "MPI flavor is $MPI_FLAVOUR."; fi |
158 |
if [ -f "$ESCRIPT_ROOT/lib/Compiled.with.openmp" ]; |
159 |
then |
160 |
ESCRIPT_WITH_OPENMP="yes" |
161 |
fi |
162 |
if [ ! -z $ESCRIPT_VERBOSE ] && [ ! -z $ESCRIPT_WITH_OPENMP ]; then echo "OpenMP enbaled."; fi |
163 |
# |
164 |
# extend path variables |
165 |
# |
166 |
export PATH=$EXTRA_PATH:$PATH |
167 |
export LD_LIBRARY_PATH=$EXTRA_LD_LIBRARY_PATH:$LD_LIBRARY_PATH |
168 |
export PYTHONPATH=$EXTRA_PYTHONPATH:$PYTHONPATH |
169 |
EXPORT_ENV="PATH, LD_LIBRARY_PATH, PYTHONPATH" |
170 |
if [ `uname` == Darwin ] |
171 |
then |
172 |
export DYLD_LIBRARY_PATH=$EXTRA_DYLD_LIBRARY_PATH:$EXTRA_LD_LIBRARY_PATH:$DYLD_LIBRARY_PATH |
173 |
EXPORT_ENV="$EXPORT_ENV, DYLD_LIBRARY_PATH" |
174 |
fi |
175 |
if [ ! -z $ESCRIPT_VERBOSE ] |
176 |
then |
177 |
echo "PATH = $PATH " |
178 |
echo "LD_LIBRARY_PATH = $LD_LIBRARY_PATH " |
179 |
echo "PYTHONPATH = $PYTHONPATH " |
180 |
if [ ! -z $DYLD_LIBRARY_PATH ]; then echo "DYLD_LIBRARY_PATH = $DYLD_LIBRARY_PATH "; fi |
181 |
fi |
182 |
#============================================== |
183 |
# |
184 |
# Ensure the variables have sensible values |
185 |
# |
186 |
if [ $MPI_FLAVOUR == "none" ] |
187 |
then |
188 |
if [ ! -z $ESCRIPT_NUM_NODES ] |
189 |
then |
190 |
echo "Warning: MPI disabled but number of nodes set. Option ignored." |
191 |
fi |
192 |
if [ ! -z $ESCRIPT_NUM_PROCS ] |
193 |
then |
194 |
echo "Warning: MPI disabled but number of processors per node set. Option ignored." |
195 |
fi |
196 |
if [ ! -z $ESCRIPT_HOSTFILE ] |
197 |
then |
198 |
echo "Warning: MPI disabled but host file is given. Option ignored." |
199 |
fi |
200 |
ESCRIPT_NUM_NODES=1 |
201 |
ESCRIPT_NUM_PROCS=1 |
202 |
else |
203 |
if [ ! -z $ESCRIPT_HOSTFILE ] |
204 |
then |
205 |
if [ -f $ESCRIPT_HOSTFILE ] |
206 |
then |
207 |
cat $ESCRIPT_HOSTFILE | sort -u > $HOSTFILE |
208 |
NUM_HOSTS = `wc -l $HOSTFILE` |
209 |
if [ ! -z $ESCRIPT_NUM_NODES ] |
210 |
then |
211 |
if [ $NUM_HOSTS -ne $ESCRIPT_NUM_NODES ] |
212 |
then |
213 |
echo "number of hosts selected in the host file $ESCRIPT_HOSTFILE needs to match the requested number of nodes $ESCRIPT_NUM_NODES." |
214 |
exit 1 |
215 |
fi |
216 |
else |
217 |
ESCRIPT_NUM_NODES = $NUM_HOSTS |
218 |
fi |
219 |
else |
220 |
echo "cannot find hostfile $ESCRIPT_HOSTFILE." |
221 |
exit 1 |
222 |
fi |
223 |
else |
224 |
HOSTFILE='' |
225 |
fi |
226 |
|
227 |
if [ -z $ESCRIPT_NUM_NODES ] |
228 |
then |
229 |
ESCRIPT_NUM_NODES=1 |
230 |
fi |
231 |
|
232 |
if [ -z $ESCRIPT_NUM_PROCS ] |
233 |
then |
234 |
ESCRIPT_NUM_PROCS=1 |
235 |
fi |
236 |
|
237 |
if [ ! -z $ESCRIPT_VERBOSE ] |
238 |
then |
239 |
echo "ESCRIPT_NUM_NODES = $ESCRIPT_NUM_NODES " |
240 |
echo "ESCRIPT_NUM_PROCS = $ESCRIPT_NUM_PROCS " |
241 |
fi |
242 |
fi |
243 |
|
244 |
if [ ! -z $ESCRIPT_WITH_OPENMP ] |
245 |
then |
246 |
if [ -z $ESCRIPT_NUM_THREADS ] |
247 |
then |
248 |
ESCRIPT_NUM_THREADS=$OMP_NUM_THREADS |
249 |
if [ -z $ESCRIPT_NUM_THREADS ] |
250 |
then |
251 |
ESCRIPT_NUM_THREADS=1 |
252 |
fi |
253 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "Number of threads is $ESCRIPT_NUM_THREADS."; fi |
254 |
fi |
255 |
else |
256 |
ESCRIPT_NUM_THREADS=1 |
257 |
fi |
258 |
# |
259 |
# Now we compute total number of Processes |
260 |
# |
261 |
(( TOTPROC=$ESCRIPT_NUM_NODES * $ESCRIPT_NUM_PROCS)) |
262 |
if [ $? -ne 0 ] #Some compute error |
263 |
then #This could happen if the args were not a number |
264 |
echo "expression of total number of processors = $ESCRIPT_NUM_NODES * $ESCRIPT_NUM_PROCS is not numerical." |
265 |
exit 1 |
266 |
fi |
267 |
# |
268 |
# Test to ensure people aren't trying to combine interactive and multi-process |
269 |
# |
270 |
if [[ ( ( -z $DOINTERACTIVE ) || ( $# -eq 0 ) ) && ( $TOTPROC -gt 1) ]] |
271 |
then |
272 |
echo "Interactive mode cannot be used with more than one process" |
273 |
exit 1 |
274 |
fi |
275 |
#========================================================================================================= |
276 |
# Must have at least one command-line arg: the python script |
277 |
if [ $# -eq 0 ] |
278 |
then |
279 |
if [ ! -z $DOBINARY ] |
280 |
then |
281 |
echo "No program to run was specified. Exiting." |
282 |
exit 1 |
283 |
fi |
284 |
fi |
285 |
|
286 |
#========================================================================================================= |
287 |
if [ ! -z $DOBINARY ] |
288 |
then |
289 |
EXEC_CMD="$@" |
290 |
else |
291 |
if [ $MPI_FLAVOUR == "none" ] |
292 |
then |
293 |
# Check to see if the python version we were compiled with matches the one of EXEC_CMD |
294 |
# We should only do this check if they are running a python script |
295 |
if [ -f $ESCRIPT_ROOT/lib/pyversion ] |
296 |
then |
297 |
compversion=`cat $ESCRIPT_ROOT/lib/pyversion` |
298 |
intversion=`$PYTHON_CMD --version 2>&1` |
299 |
if [ "$compversion" != "$intversion" ] |
300 |
then |
301 |
echo "Python versions do not match. Escript was compiled for "$compversion"." |
302 |
echo "Current version of Python appears to be "$intversion"." |
303 |
exit 1 |
304 |
fi |
305 |
fi |
306 |
if [ ! -z $DOINTERACTIVE ] |
307 |
then |
308 |
EXEC_CMD="$PYTHON_CMD -i $@" |
309 |
else |
310 |
EXEC_CMD="$PYTHON_CMD $@" |
311 |
fi |
312 |
else |
313 |
EXEC_CMD="$PYTHONMPI $@" |
314 |
fi |
315 |
fi |
316 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "Command to be executed is $EXEC_CMD."; fi |
317 |
#=============================================================================================== |
318 |
# |
319 |
# now we start to spwan things: |
320 |
# |
321 |
if [ ! -z $ESCRIPT_WITH_OPENMP ] |
322 |
then |
323 |
export OMP_NUM_THREADS=$ESCRIPT_NUM_THREADS |
324 |
EXPORT_ENV="$EXPORT_ENV, OMP_NUM_THREADS" |
325 |
fi |
326 |
|
327 |
#=============== no MPI =================================== |
328 |
if [ $MPI_FLAVOUR == "none" ] |
329 |
then |
330 |
$EXEC_CMD |
331 |
|
332 |
#=============== OpenMPI =================================== |
333 |
elif [ $MPI_FLAVOUR == "OPENMPI" ] |
334 |
then |
335 |
echo "OPENMPI not implemented yet." |
336 |
|
337 |
#=============== Intel MPI =================================== |
338 |
elif [ $MPI_FLAVOR == "INTELMPI" ] |
339 |
then |
340 |
if [ -z $HOSTFILE ] |
341 |
then |
342 |
mpdboot -n $ESCRIPT_NUM_PROCS -r ssh -f $HOSTFILE |
343 |
if [ $? -ne 0 ] |
344 |
then |
345 |
echo "mpdboot with host file $ESCRIPT_HOSTFILE for $ESCRIPT_NUM_PROCS nodes failed." |
346 |
exit 1 |
347 |
else |
348 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "mpdboot was started with host file $ESCRIPT_HOSTFILE for $ESCRIPT_NUM_PROCS nodes."; fi |
349 |
fi |
350 |
fi |
351 |
$CMD="mpiexec -n $ESCRIPT_NUM_PROCS -perhost $ESCRIPT_NUM_PROCS -envall -$EXEC_CMD" |
352 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "MPI command is $CMD."; fi |
353 |
$CMD |
354 |
if [ -z $HOSTFILE ] |
355 |
then |
356 |
mpdallexit |
357 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "mpdallexit executed."; fi |
358 |
fi |
359 |
#=============== SGI's MPIMPT =================================== |
360 |
elif [ $MPI_FLAVOR == "MPT" ] |
361 |
then |
362 |
export MPI_NUM_MEMORY_REGIONS=0 |
363 |
EXPORT_ENV="$EXPORT_ENV, MPI_NUM_MEMORY_REGIONS" |
364 |
if [ -z $HOSTFILE ] |
365 |
then |
366 |
HOST_LIST=`awk 'BEGIN{S=""}{if (S == "") { S = $0 } else {S = S "," $0}}END{print S}' $HOSTFILE` |
367 |
CMD="mpiexec $HOST_LIST $ESCRIPT_NUM_PROCS $EXEC_CMD" |
368 |
else |
369 |
CMD="mpiexec -np $TOTPROC -$EXEC_CMD" |
370 |
fi |
371 |
if [ ! -z $ESCRIPT_VERBOSE ]; then echo "MPI command is $CMD."; fi |
372 |
$CMD |
373 |
#=============== SGI's MPICH =================================== |
374 |
elif [ $MPI_FLAVOR == "MPICH" ] |
375 |
then |
376 |
echo "MPICH not implemented yet." |
377 |
else |
378 |
echo "unknown MPI falvour $MPI_FLAVOR." |
379 |
exit 1 |
380 |
fi |
381 |
exit 0 |
382 |
# Using OpenMP? |
383 |
#OMP_OPTIONS='' |
384 |
#if [ -f "$ESCRIPT_ROOT/lib/Compiled.with.openmp" ]; then |
385 |
# EXEC_CMD="$mpi_launcher $MPI_NUM_PROCS $PYTHON_MPI" |
386 |
# ESCRIPT_NUM_THREADS=$OMP_NUM_THREADS |
387 |
# OMP_OPTIONS="env OMP_NUM_THREADS=$ESCRIPT_NUM_THREADS" |
388 |
#fi |
389 |
|
390 |
# Using MPI? |
391 |
#if [ -f "$ESCRIPT_ROOT/lib/Compiled.with.mpi" ]; then |
392 |
# EXEC_CMD="$mpi_launcher $MPI_NUM_PROCS $PYTHON_MPI" |
393 |
#else |
394 |
# if [ "$TOTPROC" -ne 1 ]; then |
395 |
# echo "Escript/Finley was not compiled for MPI. You can not use the -n and -p options." |
396 |
# exit 1 |
397 |
# fi |
398 |
#fi |