Как мне объявить целое число (MPI_OFFSET_KIND) в фортране, которое требуется MPI_File_set_view, чтобы предотвратить переполнение при записи больших данных? - PullRequest
2 голосов
/ 22 января 2020

Intro:

Я пытаюсь записать большой набор данных в один файл, используя MPI IO, используя приведенный ниже код. Проблема, с которой я сталкиваюсь, заключается в том, что я получаю целочисленное переполнение (переменная disp), и, следовательно, MPI IO не работает должным образом. Я думаю, что причиной этого является объявление переменной disp (integer (kind = MPI_OFFSET_KIND) :: disp = 0) в подпрограмме write_to_file (...). Поскольку для процесса с наивысшим рангом disp переполняется.

Вопрос:

Можно ли как-то определить disp как kind = MPI_OFFSET_KIND, но с более высоким диапазоном? Я не нашел решения для этого, кроме записи в несколько файлов, но я бы предпочел запись в один файл.

Некоторый контекст:

Код - это только часть кода, который я использую для вывода (и чтения; но я вырезал эту часть из примера кода, чтобы упростить) скалярные (ivar = 1), векторные (ivar = 3) или тензорные (ivar = 3,6 или 9) значения в двоичные файлы. Размер трехмерной сетки определяется imax, jmax и kmax, где kmax разлагается процессами Px на Mk. В последнее время трехмерная сетка выросла до размера, в котором я столкнулся с описанной проблемой.

Пример кода: MPI_IO_LargeFile.f90

"" "

PROGRAM MPI_IO_LargeFile

use MPI

implicit none

integer rank, ierr, Px
integer i, j, k, cnt
integer imax, jmax, kmax, Mk
integer status(MPI_STATUS_SIZE)
integer ivars;
real*4, dimension(:,:,:,:), allocatable :: outarr, dataarr
call MPI_Init(ierr)
call MPI_Comm_size(MPI_COMM_WORLD, Px, ierr)
call MPI_Comm_rank(MPI_COMM_WORLD, rank, ierr)

imax = 256
jmax = 512
kmax = 1024
Mk = kmax / Px

if (rank < 1) print *, 'Preparing dataarr'
ivars = 6
allocate(dataarr(ivars,imax,jmax,Mk))
call RANDOM_NUMBER(dataarr)

! Output of Small File
if (rank < 1) print *, 'Output of SmallFile.txt'
ivars = 3
allocate(outarr(ivars,imax,jmax,Mk))
outarr(:,:,:,:) = dataarr(1:3,:,:,:)
call write_to_file(rank, 'SmallFile.txt', outarr)
deallocate(outarr)

! Output of Large File
if (rank < 1) print *, 'Output of LargeFile.txt'
ivars = 6
allocate(outarr(ivars,imax,jmax,Mk))
outarr(:,:,:,:) = dataarr(1:6,:,:,:)
call write_to_file(rank, 'LargeFile.txt', outarr)

deallocate(outarr)
deallocate(dataarr)
call MPI_Finalize(ierr)

CONTAINS

subroutine write_to_file(myrank, filename, arr)
  implicit none

  integer, intent(in) :: myrank
  integer :: ierr, file, varsize
  character(len=*), intent(in):: filename
  real*4, dimension(:,:,:,:), allocatable, intent(inout) :: arr
  **integer (kind=MPI_OFFSET_KIND) :: disp = 0**

  varsize = size(arr)
  disp = myrank * varsize * 4

  **write(*,*) rank, varsize, disp**

  call MPI_File_open(MPI_COMM_WORLD, filename, &
    & MPI_MODE_WRONLY + MPI_MODE_CREATE, &
    & MPI_INFO_NULL, file, ierr )
  call MPI_File_set_view(file, disp, MPI_REAL4, &
    & MPI_REAL4, 'native', MPI_INFO_NULL, ierr)
  call MPI_File_write(file, arr, varsize, &
    & MPI_REAL4, MPI_STATUS_IGNORE, ierr)
  call MPI_FILE_CLOSE(file, ierr)

end subroutine write_to_file

END PROGRAM MPI_IO_LargeFile

" ""

Вывод кода: MPI_IO_LargeFile.f90

mpif90 MPI_IO_LargeFile.f90 -o MPI_IO_LargeFile
mpirun -np 4 MPI_IO_LargeFile
 Preparing dataarr
 Output of SmallFile.txt
           2   100663296            805306368
           1   100663296            402653184
           3   100663296           1207959552
           0   100663296                    0
 Output of LargeFile.txt
           1   201326592            805306368
           0   201326592                    0
           2   201326592           1610612736
           3   201326592          -1879048192
mca_fbtl_posix_pwritev: error in writev:Invalid argument
mca_fbtl_posix_pwritev: error in writev:Invalid argument

1 Ответ

2 голосов
/ 23 января 2020

Проблема в том, что умножение в

disp = myrank * varsize * 4

переполнено, поскольку каждая переменная была объявлена ​​как целое число.

Одно решение, предоставленное @Gilles (в комментариях к вопросу), было просто измените эту строку на

disp = myrank * size(arr, kind=MPI_OFFSET_KIND) * 4

Использование size (arr, kind = MPI_OFFSET_KIND) преобразует решение в целое число вида = MPI_OFFSET_KIND, которое решает проблему переполнения.

Спасибо за ваша помощь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...