pythonmpimpi4py

Why is the python MPI allreduce returning an input list?


I have the following example problem using the allreduce function from mpi4py to find the minimum of each element in the lists across multiple processes. However, the resulting list is not correct. The output of allreduce is always one of the input lists. How can this be corrected?

Output

Rank 0: [2, 3, 6, 6, 10, 0, 9, 2, 4, 1]
Allreduce: [0, 0, 4, 4, 1, 0, 10, 10, 1, 5]
Rank 1: [4, 7, 8, 1, 3, 2, 1, 8, 2, 10]
Rank 2: [6, 2, 6, 3, 2, 3, 7, 6, 10, 4]
Rank 3: [7, 1, 0, 0, 3, 1, 6, 5, 9, 10]
Rank 4: [0, 0, 4, 4, 1, 0, 10, 10, 1, 5]
Rank 5: [1, 9, 3, 5, 9, 4, 9, 5, 4, 5]
Rank 6: [1, 4, 6, 10, 7, 2, 1, 2, 1, 3]
Rank 7: [8, 8, 8, 2, 7, 7, 9, 2, 1, 2]
Rank 8: [7, 2, 4, 10, 7, 7, 5, 2, 9, 1]
Rank 9: [3, 1, 1, 3, 5, 10, 7, 4, 2, 5]

Code

from mpi4py import MPI
import random
    
#MPI Parallelization
comm = MPI.COMM_WORLD # gets communication pool 
rank = comm.Get_rank()  # gets rank of current process 
num_ranks = comm.Get_size() # total number of processes
 
r = [random.randint(0,10) for i in range(0,10)]
    
print("Rank " + str(rank) + ": " + str(r))
  
comm.Barrier()
rr = comm.allreduce(r, op=MPI.MIN)
   
if rank == 0:
    print("Allreduce: " + str(rr))

Solution

  • Generally speaking, mpi4py works best with numpy.

    Here is an allreduce example: (do note with numpy you should use Allreduce(...) instead of allreduce(...)

    from mpi4py import MPI
    import random
    import numpy as np
        
    #MPI Parallelization
    comm = MPI.COMM_WORLD # gets communication pool 
    rank = comm.Get_rank()  # gets rank of current process 
    num_ranks = comm.Get_size() # total number of processes
     
    r = np.random.randint(0, 100, 10)
    rr = np.empty(10, dtype=int)
        
    print("Rank " + str(rank) + ": " + str(r))
      
    comm.Barrier()
    comm.Allreduce([r, MPI.INT], [rr, MPI.INT], op=MPI.MIN)
       
    if rank == 0:
        print("Allreduce: " + str(rr))
    

    In your case, I would suspect the outcome of MPI.MIN applied to a python list is not a list with the minimum elements, and hence you would get the full buffer of a given rank.