Reputation: 105
I am learning MPI4Py and I wanted to implement a simple program.
Explanation
Here, each rank has a send_array
of size rank+1
and values equal to rank+1
respectively.
rank0 = [1]
rank1 = [2 2]
rank2 = [3 3 3]
rank3 = [4 4 4 4]
I want to gather the values to rank=0
to the buffer rbuf
. Its size is equal to the total size of all local send_arrays
, i.e. 1+2+3+4 = 10
.
Program
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
send_array = np.ones(rank+1).astype(int) * (rank + 1)
print(rank, send_array)
if rank == 0:
gather_size = np.array([sum([i+1 for i in range(size)])])
print(gather_size)
rbuf = np.zeros(gather_size[0]).astype(int)
else:
gather_size = None
rbuf = None
# comm.Gatherv(sendbuf, recvbuf=(recvbuf, recvcounts, displs, datatype), root=0)
comm.Gatherv(sendbuf=send_array, recvbuf=(rbuf, (1,2,3,4),(0,1,3,6), MPI.INT), root=0)
if rank == 0:
print(rbuf, len(rbuf))
Observation/Errors/Doubts
I manually hard-coded the values to be more explicit as I have doubts on the values of recvcounts
and displs
. I am getting the following error:
comm.Gatherv(sendbuf=send_array, recvbuf=(rbuf, (1,2,3,4),(0,1,3,6), MPI.INT), root=0)
File "mpi4py/MPI/Comm.pyx", line 724, in mpi4py.MPI.Comm.Gatherv
mpi4py.MPI.Exception: MPI_ERR_TRUNCATE: message truncated
The result I am expecting is:
[1 2 2 3 3 3 4 4 4 4]
After playing around a little, I also realized that the code works if I keep the size of rbuf equal to [maximum_local_array_size*number_of_ranks
], which in this case could be 4*4
, given I have 4 ranks.
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
# send_array = np.ones(10).astype(int) * (rank + 1)
send_array = np.ones(rank+1).astype(int) * (rank + 1)
print(rank, send_array)
if rank == 0:
gather_size = np.array([16])
print(gather_size)
rbuf = np.zeros(gather_size[0]).astype(int)
else:
gather_size = None
rbuf = None
# comm.Gatherv(sendbuf, recvbuf=(recvbuf, recvcounts, displs, datatype), root=0)
comm.Gatherv(sendbuf=send_array, recvbuf=(rbuf, MPI.INT), root=0)
if rank == 0:
print(rbuf, len(rbuf))
The result I get is not what I wanted, but I don't get any errors. Note that this time I also don't specify recvcounts
and displs
. So I am not sure what exact values are used by default for these arguments, since those seem to work.
[1 0 0 0 2 2 0 0 3 3 3 0 4 4 4 4]
Upvotes: 0
Views: 59
Reputation: 8380
Here is an example on how to manually specify receive counts and displacements
from mpi4py import MPI
import numpy as np
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
size = comm.Get_size()
sbuf = np.ones(rank+1).astype(int) * (rank + 1)
def triangular(n):
return n * (n+1) // 2
if rank == 0:
gather_size = triangular(size)
rcounts = np.arange(1, size+1)
rdispls = np.array([triangular(i) for i in range(size)])
rbuf = np.zeros(gather_size, dtype=int)
else:
gather_size = None
rbuf = None
rcounts = None
rdispls = None
comm.Gatherv(sendbuf=sbuf, recvbuf=(rbuf, (rcounts, rdispls)), root=0)
if rank == 0:
print(rbuf, len(rbuf))
Upvotes: 0