mpiDL is a set of IDL bindings for the Message Passing Interface (MPI). It is used for tasks where communication between processes is required, as opposed to the independent behavior of TaskDL workers. It can make use of the multiple cores of a single computer and/or multiple nodes of a cluster. mpiDL is supported on OS X and Linux for both OpenMPI and MPICH.

As an example of using mpiDL, I will present a simple probability-based computation of pi using many cores of a computer. If you are interesting in evaluating mpiDL or require more information about, please contact me.

Setting up for using mpiDL requires placing the mpiDL lib/ directory in your IDL path and DLM path, as well as setting the MPIDL_DIR environment variable to the root of your mpiDL distribution (make sure to do it in .bashrc to make it available to non-interactive processes). Then you are ready to run an mpiDL program, such as the parallel_pi example provided in the distribution:

examples$runmpidl -np 8${PWD}/parallel_pi.sav
Running mpiexec -np 8 /home/research/mgalloy/software/mpiDL-2.4.0-Linux64/bin/mpidlstart /home/research/mgalloy/software/mpidl-r431-par/examples/parallel_pi.sav...
******************************************************************
MPIDL Version 2.4.0 - a parallel implementation of IDL
(C) Copyright 2000 - 2014, Tech-X Corp.
******************************************************************
Process 1 gave: 3.143600
Process 2 gave: 3.131600
Process 3 gave: 3.137200
Process 4 gave: 3.116400
Process 5 gave: 3.140000
Process 6 gave: 3.172800
Process 7 gave: 3.157200
The final value of pi is: 3.142686


The -np 8 argument indicates that the example should run with 8 processes; the parallel_pi example code has decided that it will have one master process collecting results and 7 workers computing pi. The example can also run with a single process, where that process both computes pi and collects the result:

examples$runmpidl -np 1${PWD}/parallel_pi.sav
Running mpiexec -np 1 /home/research/mgalloy/software/mpiDL-2.4.0-Linux64/bin/mpidlstart /home/research/mgalloy/software/mpidl-r433-434M-par/examples/parallel_pi.sav...
Process 0 gave: 3.142200
The final value of pi is: 3.142200


Also, note that a .sav file is specified. This allows a each process to use a runtime IDL license instead of a full development license.

There are two routines in the source code: parallel_pi_calcpi, which does not know about MPI and just computes an estimate of pi, and parallel_pi itself which coordinates the work using the MPI interface. By the nature of MPI, the same routine is executed in each process, but the processes are given an identifier, called the “rank”, which lets the routine decide what it should be doing. In parallel_pi, we determine that with the following code:

rank = mpidl_comm_rank()
nprocs = mpidl_comm_size()


Here, nprocs is the total number of processes and rank is an identifier from 0 to nprocs - 1. From this information, parallel_pi can determine if it will be computing pi and sending the results back or if it is the receiver of the information:

am_a_sender = (nprocs eq 1L) or (rank gt 0L)
am_a_receiver = (nprocs eq 1L) or (rank eq 0L)


This is more complicated than might seem to be required in order to handle the case of only one process which would need to be both a sender and receiver.

If it is a sender, the process must compute pi and send it back to the receiver (the rank 0 process referenced by DEST in the mpidl_send routine below):

if (am_a_sender) then begin
seedr = rank
a = dblarr(1)
a[0] = parallel_pi_calcpi(neval, seedr)
mpidl_send, a, DEST=0
endif


If it is the receiver, it allocates an array to hold the result from each sender and then receives the result from each sender in turn with mpidl_recv. Finally, it computes the average of the values to give the result:

if (am_a_receiver) then begin
mypi = dblarr(n_senders)
for j = 0L, n_senders - 1L do begin
mypi[j] = mpidl_recv(COUNT=1, SOURCE=senders[j], /DOUBLE)
print, senders[j], mypi[j], format='(%"Process %d gave: %f")'
endfor
print, total(mypi, /preserve_type) / n_senders, \$
format='(%"The final value of pi is: %f")'
endif