Hi. As promised, I'm going to post some code here today. I'll give a relatively simple example of MPI Dynamic Process Management which is good for two reasons:
a) It shows in a very basic way how to spawn processes and how mpi4py communicators work
b) It reproduces the CPU issue I described earlier
[update: blogger editor removes empty spaces and tabs from the beginning of a line and it screwed up my Python indentation entirely, so be careful]
master_test.py :
"""The following directives are not compulsory. However, my Python interpreter was complaining about encoding so I included these"""slave_test.py :
#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
from mpi4py import MPI
import sys
"""The number of processes we want to spawn"""
numprocs = 5
"""Objects comm1 and comm2 will serve for communicating with two independent of each other groups of processes. The following commands spawn these groups with 5 processes in the first one and 6 in the second one."""
comm1 = MPI.COMM_SELF.Spawn(sys.executable,args=['slave_test.py'], maxprocs=numprocs)
comm2 = MPI.COMM_SELF.Spawn(sys.executable,args=['slave_test.py'], maxprocs=numprocs+1)
print "Type some text and press Return please: "
"""Receiving user input"""
uin = raw_input()
uin1 = "FROM MASTER TO G1: " + uin
uin2 = "FROM MASTER TO G2: " + uin
"""Sending data to all processes in both groups. First parameter of the send() function is data that we want to send, second - rank of a target process, third - tag. Tags can be used for managing sequential messanges, although this can be totally ignored in the example"""
for i in range(0,numprocs):
comm1.send(uin1, i,0)
comm2.send(uin2, i,0)
#endfor
"""Since there's one more process in the second group, we need to send data there as well"""
comm2.send(uin2,numprocs,0)
"""Receiving input from the first group process with rank 4"""
data = comm1.recv(source=4,tag=1)
print "Master: ", data
#!/usr/bin/pythonNow, if you run master_test.py, but before typing in text, go to a different terminal window (that's for UNIX-like OS users. For Windows users - get yourself a Linux distro, install it, rejoice and go to a different terminal window), type "top", and see what I've been talking about earlier - 11 python processes sitting on your CPU and pretending to do a lot of work! However, you might not have this problem if you're using something different from OpenMPI (or, perhaps a newer version of OpenMPI?).
# -*- coding: iso-8859-15 -*-
from mpi4py import MPI
"""This object will serve for communicating with Master process"""
comm = MPI.Comm.Get_parent()
"""Getting the rank of the process (a number between 0 and the number of processes spawned in this group)"""
rank = comm.Get_rank()
data = ''
"""Receiving data from process with rank 0. Here it is very important to understand that comm object (initialised as MPI.Comm.Get_parent) links to the parent group where there is only one process - Master, and it has rank 0. In other words, there are 3 separate groups of processes in our system - Master (with 1 node - Master itself), first group of slaves (with 5 nodes and ranks from 0 to 4) and second group of slaves (with 6 nodes and ranks from 0 to 5)"""
data = comm.recv(source=0,tag=0)
print "Slave", comm.rank, "/", comm.size-1, ": ","["+ data + "]"
"""The following bit of code illustrates how different processes can communicate within one group and with the Master process. A message will be sent from node 0 of group 1 to node 4 of group 1 and then from node 4 - to Master"""
"""Getting a communication object for inter-group communicating"""
group_comm = MPI.COMM_WORLD
if group_comm.Get_rank()==0 and comm.size==5:
data = "FROM SLAVE 0 TO SLAVE 4: " + "[" + data + "]"
"""Sending data to process 4"""
group_comm.send(data,4,1)
#endif
if group_comm.Get_rank()==4 and comm.size==5:
data = group_comm.recv(source=0,tag=1)
print "Slave", group_comm.rank, "/", group_comm.size-1, ": ","[" + data + "]"
data = "FROM SLAVE 4 TO MASTER: " + "[" + data + "]"
"""Notice: using comm, not group_comm, since now sending data to Master. Calling the same send command on group_comm would send data to slave process 0, back to where it came from."""
comm.send(data,0,1)
#endif
No comments:
Post a Comment