Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I want to run a Python script in several parallel processes under MPI, and I need to pass command-line arguments. I'm using the argparse module in Python, but it's a little messy sometimes. If I don't specify the right arguments, all the processes complain, so I get many copies of the same error message.

I tried making only process 0 parse the arguments and then broadcast the results to the other processes, but then the other processes hang when the parsing fails and nothing gets broadcast.

How can I parse the command-line arguments, and print a readable message when the parsing fails?

share|improve this question

2 Answers 2

The extra piece I needed was to wrap a try/finally around the argument parsing step in process 0. In the finally block, broadcast something to the other processes. If parsing failed, you will broadcast None, and they can all silently exit.

from mpi4py import MPI
from time import sleep
import argparse

def parseOptions(comm):
    parser = argparse.ArgumentParser(
        description='Print some messages.')

    parser.add_argument('iteration_count', help='How many times', type=int)
    parser.add_argument('message',
                        help='What to say',
                        nargs=argparse.OPTIONAL,
                        default='Hello, World!')

    args = None
    try:
        if comm.Get_rank() == 0:
            args = parser.parse_args()
    finally:
        args = comm.bcast(args, root=0)

    if args is None:
        exit(0)
    return args

def main():
    comm = MPI.COMM_WORLD  # @UndefinedVariable
    rank = comm.Get_rank()
    size = comm.Get_size()

    args = parseOptions(comm)

    if rank == 0:
        print args.message

    for i in range(args.iteration_count):
        if i%size == rank:
            print '{} in rank {} started.'.format(i, rank)
            sleep(.5)
            print '...'
            sleep(.5)
            print '{} in rank {} ended.'.format(i, rank)

if __name__ == '__main__':
    main()

I run the code with a command like this:

mpirun -np 4 python scratch.py 13
share|improve this answer

If you have an error case, it's usually easiest to just have the processes abort rather than trying to do something fancy to clean up. In your case, you could just have the origin process (rank 0) call abort and cause everyone else to quit:

comm.abort()

That way, you don't have everyone trying to match up the results. They just automatically abort.

share|improve this answer
    
I'm new to MPI, and I didn't know about abort. That sounds easier. –  Don Kirkby Aug 4 at 21:12
    
I tried using comm.Abort(), but either I'm not using correctly, or it's a very blunt instrument. It prints a bunch of error text, including the statement that the root process has exited improperly. It complains that the calls to init and finalize were not balanced, so I'm going to stick with my original strategy of broadcasting None to tell the other processes to exit. –  Don Kirkby Aug 5 at 16:52
    
That's true that is probably prints extra output and complains. It's designed to be called in a error case, which it sounds like you are seeing. –  Wesley Bland Aug 5 at 16:54

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.