У меня есть некоторый код на Фортране, который я распараллеливаю с 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 ничего мне не выдало.