Fortran Openmp: потоки Ghost прерывают приложение при выделении - PullRequest
1 голос
/ 22 марта 2020

У меня возникла проблема, которая начинает сводить меня с ума. Как часть большого программного инструмента, я пишу модуль на Фортране для выполнения астродинамических c вычислений. Основная функциональность содержится в подпрограмме, которая использует OpenMP и другие подпрограммы для выполнения своих задач. Рабочий процесс выглядит следующим образом:

1) Подготовка - считывание в файлах

2) Запуск первого параллельного параллельного omp do

3) В зависимости от режима работы, функция может вызывать себя рекурсивно и обрабатывать отдельную часть данных (таким образом выполняя вторую omp do l oop)

4) Объединить результаты в один большой массив производного типа

Up к этому моменту все работает как ожидалось. Следующая часть, которая дает сбой:

5) Используя результаты из 4, запустите еще одну параллель l oop, чтобы продолжить обработку.

Шаг 5 иногда работает, а иногда останавливается с доступом нарушение. Это независимо от выбранного уровня оптимизации (номинально мы используем O2, но это также происходит с O0). Поэтому я запустил инспектор Intel и искал гонки данных / deadlocs, ...

Он сообщил о 5 очень странных гонках данных, которые не имеют смысла для меня, так как расположение кода либо в определении / конце подпрограммы, глобальной переменной потока чтения строки кода, подпрограммы Intel MKL или в месте чтения локального выделяемого массива, который находится в подпрограмме, которая вызывается в параллельной области. Немного почитав, я включил рекурсивный переключатель, чтобы локальный массив заканчивался в стеке. Другой анализ Инспектора был прерван тем же нарушением прав доступа. При загрузке результатов ошибок не обнаружено, но инструмент предупреждает, что из-за ненормального конца данные могут быть потеряны.

Затем я попытался поместить весь l oop в критический OMP - просто как тестовое задание. Теперь нарушение доступа исчезло, но код застрял очень рано. После обработки 15/500 объектов он просто останавливается. Это выглядело как тупик. Поэтому я продолжил поиск и прокомментировал все операторы OMP в do l oop шага 5. Интересно, что код останавливается и на 15-й итерации! Поэтому я использовал отладчик, чтобы найти вызов, где происходит бесконечное состояние ожидания. Это в последнем утверждении allocate:

Subroutine doWork(t0, Pert, allAtmosData, considerArray, perigeeFirstTimeStepUncertainties)
real(dp), intent(in)                                            :: t0                                               
type (tPert), intent(in)                                        :: Pert                                            
type (tThermosphereData), dimension(:), allocatable, intent(in) :: allAtmosData                                                                                                                                                                              
integer(i4), dimension(3), intent(in)                           :: considerArray
real(dp), dimension(:,:), allocatable, intent(out)              :: perigeeFirstTimeStepUncertainties
!Locals:
real(dp), dimension(:), allocatable                     :: solarFluxPerigeeUnc, magneticIndexUnc, modelUnc
integer(i4)                                             :: dataPoints

!Allocate memory for the computations
dataPoints = size(allAtmosData, 1)

allocate(solarFluxPerigeeUnc(0:dataPoints-1), source=0.0_dp)
allocate(magneticIndexUnc(0:dataPoints-1),    source=0.0_dp)
allocate(modelUnc(0:dataPoints-1),            source=0.0_dp)


... Subroutine body ...


!Assign outputs
allocate(perigeeFirstTimeStepUncertainties(3, 0:dataPoints-1), source=0.0_dp)
perigeeFirstTimeStepUncertainties(MGN_SOLAR_FLUX_UNCERTAINTY,:) = solarFluxPerigeeUnc
perigeeFirstTimeStepUncertainties(MGN_MAG_INDEX_UNCERTAINTY,:)  = magneticIndexUnc
perigeeFirstTimeStepUncertainties(MGN_MODEL_UNCERTAINTY,:)      = modelUnc

End Subroutine

Подпрограмма отлично работает в других местах всей программы, а также для первых 14 итераций шага 5. Однако в 15-й итерации она застревает на последней выделить, или, как мне только что удалось произвести - также приводит к нарушению доступа. Когда я приостанавливаю код с помощью отладчика, я вижу, что каким-то образом библиотека openmp была загружена и код зависает / падает в веб-интерфейсе. cpp, к которому у меня нет доступа: Call Stack at error location

Что здесь происходит? Как простое распределение может внезапно вызвать причину и активность OMP в al oop, где какой-либо оператор OMP был закомментирован? Как примечание: Если я закомментирую выделение и передам размер в качестве дополнительного аргумента, такая же ошибка произойдет при следующем выделении в коде.

Любая помощь или обходной путь очень важны! Я уже гуглил о том, как закрыть любой предыдущий пул потоков, так что определенно не осталось активности потока-призрака omp, но, видимо, нет никакого способа сделать это. Также в конечном итоге l oop будет работать параллельно.

РЕДАКТИРОВАТЬ: Я только что провел второй тест на машине с 2018 v5. Это также показывает, что оператор allocate приводит к вызову for_alloc_allocatable (), а затем к операторам OMP. Также показан оператор mov, в котором происходит сбой программы: enter image description here

Я предполагаю, что что-то, вероятно, вызывает повреждение памяти во втором рекурсивном OMP l oop, так как каким-то образом выделяется перенаправлен на выделение памяти в пуле потоков, однако все потоки, кроме основного, должны быть пассивными? Я не могу читать ассемблер, но я был удивлен, обнаружив, что TBB используется OpenMp? Может ли это быть ошибкой в ​​TBB?

...