У меня возникла проблема с OpenMP и общими переменными, которые я не могу понять. Все, что я делаю, - в Fortran 90/95.OpenMP и общая переменная в Fortran, которые не являются общими
Вот моя проблема: у меня есть параллельная область, определенная в моей программе main
, с предложением DEFAULT(SHARED)
, в котором я вызываю подпрограмму, которая выполняет некоторые вычисления. У меня есть локальная переменная (массив), которую я выделяю и на которой выполняю вычисления. Я ожидал, что этот массив будет использоваться совместно (из-за предложения DEFAULT(SHARED)
), но похоже, что это не так.
Вот пример того, что я пытаюсь сделать, и воспроизвести ошибку я получаю:
program main
!$ use OMP_LIB
implicit none
integer, parameter :: nx=10, ny=10
real(8), dimension(:,:), allocatable :: array
!$OMP PARALLEL DEFAULT(SHARED)
!$OMP SINGLE
allocate(array(nx,ny))
!$OMP END SINGLE
!$OMP WORKSHARE
array = 1.
!$OMP END WORKSHARE
call compute(array,nx,ny)
!$OMP SINGLE
deallocate(array)
!$OMP END SINGLE
!$OMP END PARALLEL
contains
!=============================================================================
! SUBROUTINES
!=============================================================================
subroutine compute(array, nx, ny)
!$ use OMP_LIB
implicit none
real(8), dimension(nx,ny) :: array
integer :: nx, ny
real(8), dimension(:,:), allocatable :: q
integer :: i, j
!$OMP SINGLE
allocate(q(nx,ny))
!$OMP END SINGLE
!$OMP WORKSHARE
q = 0.
!$OMP END WORKSHARE
print*, 'q before: ', q(1,1)
!$OMP DO SCHEDULE(RUNTIME)
do j = 1, ny
do i = 1, nx
if(mod(i,j).eq.0) then
q(i,j) = array(i,j)*2.
else
q(i,j) = array(i,j)*0.5
endif
end do
end do
!$OMP END DO
print*, 'q after: ', q(1,1)
!$OMP SINGLE
deallocate(q)
!$OMP END SINGLE
end subroutine compute
!=============================================================================
end program main
Когда я выполняю это так, я получаю ошибку сегментации, поскольку локальный массив q
выделяется на одном потоке, но не на других, и когда другие пытаются получить к нему доступ в памяти, он сработает.
Если я избавлюсь от SINGLE
области локального массива q
выделяется (хотя иногда он выходит из строя, которые имеют смысл, если разные потоки пытаются передать его в то время как это уже происходит (и на самом деле это меня озадачивает, почему это делает не сбой каждый раз)), но тогда ясно, что массив q
является закрытым (поэтому один поток возвращает мне ожидаемое значение, тогда как другие возвращают мне что-то еще).
Это действительно озадачило меня, почему массив q
не является общим, хотя я объявил свою параллельную область с предложением DEFAULT(SHARED)
. И так как я в сиротской подпрограмме, я не могу объявить явно q
как общедоступный, так как известен только в подпрограмме compute
... Я застрял в этой проблеме до сих пор, я не мог найти обходное решение.
Нормально ли это? Должен ли я ожидать такого поведения? Есть ли обходной путь? Пропустить что-то очевидное?
Любая помощь была бы высоко оценена!
Спасибо Владимиру за объяснение и обходной путь! Действительно, с атрибутом 'save' он работает, мой пример компилируется и запускается. Благодаря! – MBR