У меня возникла проблема, которая начинает сводить меня с ума. Как часть большого программного инструмента, я пишу модуль на Фортране для выполнения астродинамических 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, к которому у меня нет доступа:
Что здесь происходит? Как простое распределение может внезапно вызвать причину и активность OMP в al oop, где какой-либо оператор OMP был закомментирован? Как примечание: Если я закомментирую выделение и передам размер в качестве дополнительного аргумента, такая же ошибка произойдет при следующем выделении в коде.
Любая помощь или обходной путь очень важны! Я уже гуглил о том, как закрыть любой предыдущий пул потоков, так что определенно не осталось активности потока-призрака omp, но, видимо, нет никакого способа сделать это. Также в конечном итоге l oop будет работать параллельно.
РЕДАКТИРОВАТЬ: Я только что провел второй тест на машине с 2018 v5. Это также показывает, что оператор allocate приводит к вызову for_alloc_allocatable (), а затем к операторам OMP. Также показан оператор mov, в котором происходит сбой программы:
Я предполагаю, что что-то, вероятно, вызывает повреждение памяти во втором рекурсивном OMP l oop, так как каким-то образом выделяется перенаправлен на выделение памяти в пуле потоков, однако все потоки, кроме основного, должны быть пассивными? Я не могу читать ассемблер, но я был удивлен, обнаружив, что TBB используется OpenMp? Может ли это быть ошибкой в TBB?