Reputation: 105
I am working on some MPI code for Parallel IO. Say I have an array [2 ,5,6,9,0,4,3,1,8,7 ] written in a File, and I have 2 processes.
I define File views to read part of this file. Process 0 sees : 2 ,5,6,9,0 (5 elements) Process 1 sees : 4,3,1,8,7 (5 elements) Both processes call a sort function . As a result of sort function, Process 0 has : 0,1,2,3 (4 elements) Process 1 has : 4,5,6,7,8,9 (6 elements)
Now i need to write this output to a new output file. Process 0 would write it correctly as it writes at offset 0. But how would Process 1 know the offset where to write the file ? I know I need to define a File view to write , BUT what would be the new displacement. I kind of think MPI_Exscan can do it.. But I am not sure how... Can someone help please ??
Thanks in Advance
Upvotes: 1
Views: 552
Reputation: 50927
Sure; you use MPI_Exscan
with MPI_SUM
on the local number of elements to get the total number to the "left" of you, and use that in your view (either as an offset, or in the type you create to define your view).
Here's a little Fortran program where each rank generates a "random" (well, 2*rank+1
) sized array of characters ('0' for rank 0, etc), uses MPI_Exscan to find out what offset it should use when writing, and then writes:
program testexscan
use mpi
implicit none
integer :: nelements, nleft, total
character, allocatable, dimension(:) :: array
integer :: rank, nprocs, ierr, fh
integer(kind=MPI_OFFSET_KIND) :: disp
call MPI_Init(ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, nprocs, ierr)
call generatedata(rank, array)
nelements = size(array)
call MPI_Exscan (nelements, nleft, 1, MPI_INTEGER, MPI_SUM, MPI_COMM_WORLD, ierr)
print *, 'rank = ', rank, ' nelements = ', nelements, ' nleft= ', nleft
call MPI_File_open(MPI_COMM_WORLD, 'output.txt', ior(MPI_MODE_WRONLY,MPI_MODE_CREATE), &
MPI_INFO_NULL, fh, ierr)
disp = nleft * 1 ! offset in bytes
call MPI_File_set_view(fh, disp, MPI_CHARACTER, MPI_CHARACTER, "native", MPI_INFO_NULL, ierr )
call MPI_File_write_all(fh, array, nelements, MPI_CHARACTER, MPI_STATUS_IGNORE, ierr)
call MPI_File_close(fh, ierr)
deallocate(array)
call MPI_Finalize(ierr)
contains
subroutine generatedata(rank, arr)
character, dimension(:), allocatable, intent(inout) :: arr
integer, intent(in) :: rank
nelements = rank * 2 + 1
allocate(array(nelements))
array = char(ichar("0")+rank)
end subroutine generatedata
end program testexscan
Running this gives:
$ mpif90 -o testexscan testexscan.f90
$ mpirun -np 4 ./testexscan
rank = 0 nelements = 1 nleft= 0
rank = 1 nelements = 3 nleft= 1
rank = 2 nelements = 5 nleft= 4
rank = 3 nelements = 7 nleft= 9
$ cat output.txt
0111222223333333
Upvotes: 4
Reputation: 8273
Your description is a bit vague, but in any case, process 1 can just send a message to process 2 that contains the offset to be used.
Upvotes: 0