0

I am writing a parallel program in Fortran77. I have the following problem:

  1. I have N number of processors.
  2. Each processor contains an array A of size S.
  3. Using some function, on every processor (say rank X), I calculate the value of two integers Y and Z, where Z < S (the values of Y and Z are different on every processor).
  4. I want to get the value of A(Z) on processor Y to processor X.

I thought of first sending the numerical value X to processor Y from processor X and then sending A(Z) from processor Y to processor X. But it is not possible as processor Y does not know the numerical value X and so it won't know from which processor to receive the numerical value X from.

I tried but I haven't been able to come up with any code which can implement this action. So I am not posting any codes.

Edit:

I will try to explain it with an example. Suppose I am on processor X=(say 2). On processor 2, I calculate the value of two integers, Y=(say 34) and Z=say(5). I want to use the value of A(5) on processor 34 for a computation on processor 2. How do I do this?

Edit:

Someone on a MPI forum gave me this code which illustrates the use of mpi_get very clearly:

program var_access

implicit none
include 'mpif.h'

integer ierr
integer i
integer rank
integer disp_int
integer X, Y, Z
integer S
parameter (S = 10)
integer A(S)
integer AYS
integer win, NP
integer (kind=MPI_ADDRESS_KIND) lowerbound, size, realextent, disp_aint
integer n
integer, allocatable :: seed(:)
real rnd(3)

call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD,NP,ierr)
call MPI_Comm_rank(MPI_COMM_WORLD,rank,ierr)

! Produce random numbers
call random_seed(size = n)
allocate(seed(n))
do i=1, n
    seed(i) = i
end do
call random_seed(put = seed)
call random_number(rnd)
X = floor(NP*rnd(1))
Y = floor(NP*rnd(2))
Z = ceiling(S*rnd(3))

! Determine the size of one data element in the array in bytes
call MPI_Type_get_extent(MPI_INT, lowerbound, realextent, ierr)
disp_int = realextent
! Determine the size of the entire data array in bytes
size = S * realextent
! create the actual memory window
call MPI_Win_create(A, size, disp_int ,MPI_INFO_NULL, MPI_COMM_WORLD, win, ierr)

! Fill array A with some data
do i = 1, S
    A(i) = S * rank + i
    if (rank.eq.Y) write (*,*) rank, i, A(i), rnd(1), rnd(2), rnd(3)
end do


! Synchronize window
call MPI_Win_fence(0, win, ierr)
if(rank .eq. X) then
    disp_aint = Z - 1
    call MPI_Get(AYS, 1, MPI_INT, Y, disp_aint, 1, MPI_INT, win, ierr)
endif

! Synchronize window, completing all accesses to it
call MPI_Win_fence(0, win, ierr)
if(rank .eq. X) then
    write (*,*) Y,Z,"# ", AYS
endif

call MPI_Win_free(win, ierr)
call MPI_Finalize(ierr)

end program var_access
Hristo Iliev
  • 72,659
  • 12
  • 135
  • 186
Pradeep Kumar Jha
  • 877
  • 4
  • 15
  • 30
  • 8
    I no longer help people writing new programs in FORTRAN77, I think it's unethical, a bit like a medical school teaching doctors to amputate limbs without anaesthetic. It's the 21st century and even the free compilers provide nearly-complete implementations of Fortran 2003. – High Performance Mark Jan 09 '14 at 11:13
  • I am sorry but I am supposed to add a subroutine to an already existing bigger code, that does not belong to me, and is all written in F77. I don't have a choice here. – Pradeep Kumar Jha Jan 09 '14 at 11:24
  • 2
    Modern Fortran can of course be mixed with Fortran 77. – Vladimir F Героям слава Jan 09 '14 at 11:39
  • Have you researched OpenMP and MPI? – M. S. B. Jan 09 '14 at 15:08
  • You say, that this is Fortran 77, but from the rest of the description in your question it reads as if you are trying to use coarrays which are a F2008 feature? What kind of parallelism do you actually use? – haraldkl Jan 09 '14 at 21:20
  • I would try this : first, fill an array of `int` with zeros. then, on proc X, `array[Y]=1`. Then use `mpi_allreduce` : every processus know how many values of `A` it will send (say `M`). Then perform non-blocking send (`mpi_isend`) of `Z` from `X` to `Y` and receive messages (`M`, use MPI_ANY_SOURCE). The 'reply' processus `X` will be found in the output argument `status` of `mpi_recv`. Perform `M`non-blocking send from `Y` to `X`. Last : receive `A(Z)` on proc `X` Finish with `mpi_waitall`. Non-blocking send will avoid deadlock. I am afraid this solution will not speed up your code ! – francis Jan 09 '14 at 21:39
  • @HighPerformanceMark I am sorry that my language was confusing. I will try to explain it with an example. Suppose I am on processor X=(say 2). On processor 2, I calculate the value of two integers, Y=(say 34) and Z=say(5). I want to use the value of A(5) on processor 34 for a computation on processor 2. How do I do this? I hope it is more clear this time :| – Pradeep Kumar Jha Jan 15 '14 at 06:59
  • @francis Thank you for your detailed reply, but I couldn't understand it very well – Pradeep Kumar Jha Jan 15 '14 at 07:00
  • @haraldki I am using mpif90 compiler. That's all I know. – Pradeep Kumar Jha Jan 15 '14 at 07:00
  • I suspect that you are looking for MPI-2's *one-sided communications*, specifically the routine *mpi_get*. Do some research, write some code, return with a new question if / when you get stuck. – High Performance Mark Jan 15 '14 at 10:09
  • That code is not FORTRAN 77. – Vladimir F Героям слава May 15 '16 at 19:29

1 Answers1

0

But it is not possible as processor Y does not know the numerical value X and so it won't know from which processor to receive the numerical value X from.

This is possible actually. It's enough you use MPI_ANY_SOURCE as the source rank of the MPI_Recv. You can detect which processor has actually sent the data, by inspecting the returned STATUS.

Sigi
  • 4,826
  • 1
  • 19
  • 23