mpi изменяет переменную, которую не должен [дублировать]

У меня есть некоторый код на Фортране, который я распараллеливаю с MPI, который делает действительно странные вещи. Во-первых, есть переменная nstartg, которую я транслирую из процесса босса всем рабочим:

call mpi_bcast(nstartg,1,mpi_integer,0,mpi_comm_world,ierr)

Переменная nstartg больше никогда не изменяется в программе. Позже процесс-босс отправляет eproc элементов массива edge рабочим:

if (me==0) then
    do n=1,ntasks-1
        (determine the starting point estart and the number eproc
         of values to send)
        call mpi_send(edge(estart),eproc,mpi_integer,n,n,mpi_comm_world,ierr)
    enddo
endif

с соответствующим оператором приема, если me не равно нулю. (Я опустил некоторый другой код для удобства чтения; есть веская причина, по которой я не использую scatterv.)

Вот где все становится странным: переменная nstartg изменяется на n вместо того, чтобы сохранять свое фактическое значение. Например, на процессе 1 после mpi_recv, nstartg = 1, а на процессе 2 он равен 2 и так далее. Более того, если я изменю приведенный выше код на

call mpi_send(edge(estart),eproc,mpi_integer,n,n+1234567,mpi_comm_world,ierr)

и соответствующим образом измените тег в соответствующем вызове на mpi_recv, затем в процессе 1 nstartg = 1234568; в процессе 2 nstartg = 1234569 и т.д.

Что, черт возьми, происходит? Все, что я изменил, это тег, который mpi_send/recv использует для идентификации сообщения; при условии, что теги уникальны, чтобы сообщения не смешивались, это ничего не должно изменить, и все же это изменяет совершенно не связанную переменную.

В процессе босса nstartg не изменяется, так что я могу исправить это, снова транслируя его, но вряд ли это реальное решение. Наконец, я должен упомянуть, что компиляция и запуск этого кода с использованием электрического забора не обнаружила никаких переполнений буфера, а -fbounds-check ничего мне не выдало.


person korrok    schedule 06.12.2012    source источник
comment
Не могли бы вы опубликовать наиболее краткую версию кода, воспроизводящего это поведение?   -  person milancurcic    schedule 06.12.2012
comment
Вы уверены, что ваше количество целых чисел, заданное eproc, верно?   -  person haraldkl    schedule 06.12.2012


Ответы (1)


Наиболее вероятная причина заключается в том, что вы передаете скаляр INTEGER в качестве фактического аргумента status в MPI_RECV, когда на самом деле он должен быть объявлен как массив с размером, зависящим от реализации, доступным как константа MPI_STATUS_SIZE:

INTEGER, DIMENSION(MPI_STATUS_SIZE) :: status

or

INTEGER status(MPI_STATUS_SIZE)

Тег сообщения записывается в одно из полей состояния операцией приема (его индекс, зависящий от реализации, доступен как константа MPI_TAG, а значение поля можно получить как status(MPI_TAG)), и если ваше status является просто скалярным INTEGER, то несколько других локальные переменные будут перезаписаны. В вашем случае просто так получается, что nstartg падает чуть выше status в стеке.

Если вас не волнует статус приема, вы можете передать вместо него специальную константу MPI_STATUS_IGNORE.

person Hristo Iliev    schedule 06.12.2012
comment
Использование mpi_status_ignore исправило это, большое спасибо! - person korrok; 06.12.2012