Прохождение 3D-массивов с использованием MPI_ALLGATHERV
Я пытаюсь передать трехмерные массивы всем другим процессам, используя MPI_ALLGATHERV. v1 является общим массивом блоков.
parameter (nprocz=48,nzro=1)
do 1 i=i101,i102
do 2 j = je0, je1-1
do 2 k = ke0, ke1
v1(k,j,i) = v1(k,j,i)*0.015*float(i-iv0)
2 continue
1 continue
nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
if (mpirank .le. nprocz-2) then
i101=ie0+(mpirank*nmpi01)
i102=ie0+(mpirank+1)*nmpi01-1
else
i101=ie0+(mpirank*nmpi01)
i102=iv0-1
endif
scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1)
rcount(mpirank+1)=scount
displs(mpirank+1)=mpirank*scount+1 call
MPI_ALLGATHERV(v1(1,1,i101),scount,MPI_REAL,v1(1,1,1) ,rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004)
но я получил эту ошибку столько же, сколько мои процессы:
Fatal error in PMPI_Allgatherv: Internal MPI error!, error stack:
...
MPIR_Localcopy(378).......: memcpy arguments alias each other, dst=0x7ccddb44
src=0x7ccddb40 len=3642752
тогда я попробовал MPI_IN_PLACE вот так:
MPI_ALLGATHERV(MPI_IN_PlACE,scount,MPI_REAL,v1(1,1,1),
rcount,displs,MPI_REAL,MPI_COMM_WORLD,ierr004)
но память использовалась постепенно, пока пробрам не сломался.
1 ответ
MPI_ALLGATHERV
требует, чтобы каждый ранг определял размеры и смещения для каждого ранга в коммуникаторе. Что вы делаете, вы заполняете значения только для одного ранга:
rcount(mpirank+1)=scount
displs(mpirank+1)=mpirank*scount+1
Вместо этого вы должны перебрать ряды и вычислить все элементы rcount
а также displs
в каждом ранге:
integer :: myscount, myi101
displs(1) = 0
do rank = 0, nprocz-1
nmpi01=floor((iv0-ie0-nzro)/(nprocz-1))
if (rank .le. nprocz-2) then
i101=ie0+(rank*nmpi01)
i102=ie0+(rank+1)*nmpi01-1
else
i101=ie0+(rank*nmpi01)
i102=iv0-1
endif
scount=(i102-i101+1)*(je1-je0)*(ke1-ke0+1)
rcount(rank+1)=scount
if (rank .gt. 0) then
displs(rank+1) = displs(rank) + rcount(rank)
endif
if (rank .eq. mpirank) then
myscount = scount
myi101 = i101
end if
end do
scount = myscount
i101 = myi101
call mpi_allgatherv(...)
Обратите внимание также, что способ displs
вычисляется, вероятно, неправильно. Если полученные данные должны быть размещены без промежутков между ними, должно соблюдаться следующее соотношение: displs(i) = sum(rcount(1:i-1))
, Изменить: я изменил код выше с тем, который правильно вычисляет элементы displs
массив.