2013-03-05 2 views
2

У меня возникла проблема с 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 ... Я застрял в этой проблеме до сих пор, я не мог найти обходное решение.

Нормально ли это? Должен ли я ожидать такого поведения? Есть ли обходной путь? Пропустить что-то очевидное?

Любая помощь была бы высоко оценена!

ответ

3

Массив q определяется Внутри вызываемой подпрограммы. Каждый поток вызывает эту подпрограмму самостоятельно, и поэтому каждый поток будет иметь свою собственную копию. Директива shared во внешней подпрограмме не может изменить это. Попробуйте объявить его с атрибутом save.

+0

Спасибо Владимиру за объяснение и обходной путь! Действительно, с атрибутом 'save' он работает, мой пример компилируется и запускается. Благодаря! – MBR

7

q - это объект, который находится внутри области, но не внутри конструкции, в терминах OpenMP-речи. Подпрограмма, которая q является локальной, находится в процедуре, которая вызывается во время параллельной конструкции, но сама q не лексически появляется между директивами PARALLEL и END PARALLEL.

Правила обмена данными для таких объектов в OpenMP затем определяют, что q является приватным.

Предложения о совместном использовании данных, такие как DEFAULT (SHARED) и т. Д. Применяются только к вещам, которые появляются в самой конструкции (вещи, которые лексически появляются между PARALLEL и END PARALLEL). (Они не могут применяться к вещам в регионе в целом - процедуры, называемые в регионе, могут быть отдельно составлены и могут быть вызваны за пределами любых параллельных конструкций.)

+0

Спасибо за это объяснение, теперь я получаю его. Есть ли обходной путь? – MBR

Смежные вопросы