[Wien] some comments on parallel execution of wien2k
Sergiu Arapan
sergiu.arapan at gmail.com
Wed Dec 23 13:08:12 CET 2009
Dear wien2k users and developers,
I would like to post few comments on running parallel version of wien2k
on a distributed memory cluster. I'm using the most recent version of
wien2k (09.2) on a Linux-based cluster with 805 HP ProLiant DL140 G3
nodes, each node consisting of Intel Xeon E5345 Quad Core Processor 2.33
GHz, 4 MB Level 2 cache, interconnected by Next generation Infiniband
interconnect. Operating system is CentOS 5 64-bit Linux and resource
manager is SLURM. I compiled source code with Intel compilers (ifort
10.1.017), Intel built OpenMPI (mpif90 1.2.7) and linked with MKL
(10.0.1.014), FFTW (2.1.5) and corresponding OpenMPI libs.
My first comment concerns the implementation of the MPI on fine grain
parallelization. Within the current version of wien2k, the module
lap2w_mpi crashes if N_noneq_atoms (number of nonequivalent atoms in
case.struc file) is not a multiple of N_cpus (number of processors to
run lapw2_mpi). This strange behavior was reported in a recent post by
Duy Le with the subject “[Wien] MPI problem for LAPW2”
(http://zeus.theochem.tuwien.ac.at/pipermail/wien/2009-September/012042.html).
He noticed that for a system consisting of 21 (nonequivalent) atoms the
program runs only for 3 or 7 cpus. He managed to cure the problem by
setting lapw2_vector_split:$N_cpus, but without a reasonable
explanation. However, one can get a hint by looking at lap2w source
files and the output of lapw2_mpi. Let's consider, for example, the
cd16te15sb.struct from $WIENROOT/example_struct_files, which describes a
structure with 5 nonequivalent atoms. Let's run it on a computer node
with 8 cpus with the following .machines file:
granularity:1
1:n246:8
lapw0:n246:8
extrafine:1
Here are some lines from the resulting case.dayfile:
> lapw0 -p (19:41:09) starting parallel lapw0 at Tue Dec 22 19:41:09
CET 2009
-------- .machine0 : 8 processors
mpirun --verbose -np 8 --hostfile .machine0 $WIENROOT/lapw0_mpi lapw0.def
Tue Dec 22 19:41:27 CET 2009 -> all processes done.
…..................................................................................
> lapw1 -c -p (19:41:28) starting parallel lapw1 at Tue Dec 22 19:41:28
CET 2009
-> starting parallel LAPW1 jobs at Tue Dec 22 19:41:28 CET 2009
1 number_of_parallel_jobs
-------- .machine1 : 8 processors : weight 1
mpirun --verbose -np 8 --hostfile .machine1 $WIENROOT/lapw1c_mpi
lapw1_1.def
waiting for all processes to complete
Tue Dec 22 19:48:26 CET 2009 -> all processes done.
….....................................................................................
> lapw2 -c -p (19:48:28) running LAPW2 in parallel mode
running parallel lapw2
mpirun --verbose -np 8 --hostfile .machine1 $WIENROOT/lapw2c_mpi
lapw2_1.def 1
sleeping for 1 seconds
waiting for processes:
** LAPW2 crashed!
….....................................................................................
The job crashed with the following error message:
[n246:15992] *** An error occurred in MPI_Comm_split
[n246:15992] *** on communicator MPI_COMM_WORLD
[n246:15992] *** MPI_ERR_ARG: invalid argument of some other kind
[n246:15992] *** MPI_ERRORS_ARE_FATAL (goodbye)
Now, if one take a look at case.output2_1_proc_n (n=1,2,..,7), one see
the following header (here is the case of case.output2_1_proc_1):
init_parallel_2 1 8 1 8 2
MPI run on 8 processors in MPI_COMM_WORLD
8 processors in MPI_vec_COMM (atoms splitting)
1 processors in MPI_atoms_COMM (vector splitting)
myid= 1
myid_atm= 1
myid_vec= 1
time in recpr: 0.820000000000000
One can find the following lines in the lapw2.F source file (lines
129-137):
#ifdef Parallel
write(6,*) 'MPI run on ',npe,' processors in MPI_COMM_WORLD'
write(6,*) ' ',npe_atm,' processors in MPI_vec_COMM (atoms splitting)'
write(6,*) ' ',npe_vec,' processors in MPI_atoms_COMM (vector splitting)'
write(6,*) ' myid= ',myid
write(6,*) ' myid_atm= ',myid
write(6,*) ' myid_vec= ',myid
write(6,*) ' '
#endif
which generate this output.
If I correctly understand, npe is the total number of cpus, npe_atm is
the number of cpus for parallelization over atoms, and npe_vec the
number of cpus for additional parallelization of the density over
vectors (I think that MPI_vec_COMM and MPI_atoms_COMM should be swapped).
One can also find the following lines (306-311) in the l2main.F file:
! ---------------------------------
! START LOOP FOR ALL ATOMS
! ---------------------------------
non_equiv_loop: do jatom_pe=1,nat,npe_atm
jatom=jatom_pe+myid_atm
from which I can understand that the loop is over nonequivalent atoms
nat with step npe_atom.
Now let's do some changes in the lapw2para to run lapw2_mpi on 5 cpus,
and take a look at case.dayfile and case.output2_1_proc_1 files.
Here are lines from case.dayfile:
> lapw0 -p (20:08:14) starting parallel lapw0 at Tue Dec 22 20:08:14
CET 2009
Tue Dec 22 20:08:14 CET 2009 -> Setting up case Cd16Te15Sb for parallel
execution
-------- .machine0 : 8 processors
mpirun --verbose -np 8 --hostfile .machine0 $WIENROOT/lapw0_mpi lapw0.def
Tue Dec 22 20:08:33 CET 2009 -> all processes done.
….............................................................................
> lapw1 -c -p (20:08:34) starting parallel lapw1 at Tue Dec 22 20:08:34
CET 2009
-> starting parallel LAPW1 jobs at Tue Dec 22 20:08:34 CET 2009
mpirun --verbose -np 8 --hostfile .machine1 $WIENROOT/lapw1c_mpi
lapw1_1.def
waiting for all processes to complete
Tue Dec 22 20:15:32 CET 2009 -> all processes done.
…...................................................................................................
> lapw2 -c -p (20:15:33) running LAPW2 in parallel mode
machines: n383
running parallel lapw2
mpirun --verbose -np 5 --hostfile .machine1 $WIENROOT/lapw2c_mpi
lapw2_1.def 1
sleeping for 1 seconds
waiting for processes:
n383 0.014u 0.008s 0:51.32 0.0% 0+0k 0+0io 0pf+0w
…................................................
:ENERGY convergence: 0 0 .0004326450000000
:CHARGE convergence: 1 0.001 -.0000259
ec cc and fc_conv 1 1 1
> stop
This time job terminated successfully, and first lines of
case.output2_1_proc_1 read as:
init_parallel_2 1 5 1 5 2
MPI run on 5 processors in MPI_COMM_WORLD
5 processors in MPI_vec_COMM (atoms splitting)
1 processors in MPI_atoms_COMM (vector splitting)
myid= 1
myid_atm= 1
myid_vec= 1
time in recpr: 0.820000000000000
:POS002: AT.NR. -2 POSITION = 0.12426 0.12426 0.12426 MULTIPLICITY = 4
…....................................................................................................................................
Now, let's see what is going on when lapw2_vector_split:N_cpus is set in
.machines file:
granularity:1
1:n21:8
lapw2_vector_split:8
lapw0:n21:8
extrafine:1
One can read the following lines from case.dayfile:
> lapw2 -c -p (21:06:51) running LAPW2 in parallel mode
machines: n21
running parallel lapw2
mpirun --verbose -np 8 --hostfile .machine1
/home/x_serar/wien2k/09.2/openmpi/lapw2c_mpi lapw2_1.def 1
sleeping for 1 seconds
waiting for processes:
n21 0.027u 0.012s 1:26.55 0.0% 0+0k 0+0io 0pf+0w
….......................................................................................................
:ENERGY convergence: 0 0 .0000601700000000
:CHARGE convergence: 1 0.001 -.0006113
ec cc and fc_conv 1 1 1
> stop
The first lines of case.output2_1_proc_1 read as:
init_parallel_2 1 8 8 1 1
MPI run on 8 processors in MPI_COMM_WORLD
1 processors in MPI_vec_COMM (atoms splitting)
8 processors in MPI_atoms_COMM (vector splitting)
myid= 1
myid_atm= 1
myid_vec= 1
time in recpr: 0.810000000000000
0 0.191606E+00 -0.475342E+00 -0.217499E+00 -0.295484E+00 0.795881E-01 4 4 4
….......................................................................................................................................................
That is, there is no atom splitting and npe_atm=1 is a divisor of the
number of nonequivalent atoms. This result npe_atm=1 becomes clear if
one take a look at modules.F, SUBROUTINE init_parallel_2 (line 78):
...................................................................................
npe_atm=npe/npe_vec
…...............................................................................
Thus, the crash of lapw2_mpi is not related to memory issues, but to the
way the parallelization is implemented. My analysis is, of course,
superficial, and I can not say whether there is a bug in the lapw2_mpi
module. But I think that this issue requires some attention from
developers.
My second comment is that you do not need to connect through ssh to
allocated processors on different computer nodes in order to run
lapw1(c) or lapw2(c) (the case of parallelization over k-points). You
can run your parallel processes by invoking mpirun.
First, set up "setenv WIEN_MPIRUN 'mpirun -np _NP_ --hostfile _HOSTS_
_EXEC_'” in $WIENROOT/parallel_options.
Second, instead of line “(cd $PWD;$t $exe ${def}_$loop.def;rm -f
.lock_$lockfile[$p]) >>.time1_$loop &” in lapw1para (line 406) use the
following two lines:
“set ttt=(`echo $mpirun | sed -e "s^_NP_^$number_per_job[$p]^" -e
"s^_HOSTS_^.machine$p^" -e "s^_EXEC_^$WIENROOT/${exe} ${def}_$loop.def^"`)”
and
“(cd $PWD;$t $ttt;rm -f .lock_$lockfile[$p]) >>.time1_$loop &”
similar to mpi execution.
In the same fashion, in lapw2para instead of line 314 “(cd $PWD;$t $exe
${def}_${loop}.def $loop;rm -f .lock_$lockfile[$p]) >>.time2_$loop &”
use the following 2 lines:
“set ttt=(`echo $mpirun | sed -e "s^_NP_^$number_per_job2[$loop]^" -e
"s^_HOSTS_^.machine$mach[$loop]^" -e "s^_EXEC_^$WIENROOT/${exe}
${def}_$loop.def $loop^"`)”
and
“(cd $PWD;$t $ttt $vector_split;rm -f .lock_$lockfile[$p])
>>.time2_$loop &”.
I hope you will find these comments useful :) .
Regards and Marry Christmas,
Sergiu Arapan
More information about the Wien
mailing list