Fortran & OpenMP: как объявить и выделить выделяемый массив THREADPRIVATE - PullRequest
0 голосов
/ 02 февраля 2019

У меня был серийный код, в котором я объявлял кучу переменных в модулях, а затем use эти модули в остальной части моей программы и подпрограмм.Сейчас я пытаюсь распараллелить этот код.Есть часть кода, которую я хочу запустить параллельно, которая, кажется, работает, за исключением одного массива, gtmp.Я хочу, чтобы у каждого потока была своя собственная версия gtmp, и я хочу, чтобы эта версия была приватной для соответствующего потока, поэтому я использовал директиву threadprivate.gtmp используется только внутри параллельной области кода или внутри подпрограмм, которые вызываются только из параллельной части кода.

Сначала я выделил gtmp в последовательной части кода передпараллельной части, но это было проблемой, потому что тогда только «версия» главного потока gtmp была выделена, а «версии» другого потока gtmp имели size 1, а не ожидаемый выделенный размерgtmp, (это было показано оператором "test" print).Я думаю, что это произошло, потому что главный поток - единственный поток, выполняющий код в последовательных частях.Итак, я переместил линию allocate в параллельную область, что позволило всем потокам иметь соответствующие размеры / распределенные массивы gtmp, но, поскольку моя параллельная область находится внутри цикла, я получаю ошибку, когда программа пытается выделить gtmp второй раз во второй итерации цикла r.

Примечание: в других местах кода все остальные переменные в mymod имеют заданные значения.

Вот упрощенная часть кода, в которой возникла проблема:

module mymod
  integer :: xBins, zBins, rBins, histCosThBins, histPhiBins, cfgRBins
  real(kind=dp),allocatable :: gtmp(:,:,:)
end module mymod

subroutine compute_avg_force
  use mymod
  implicit none
  integer :: r, i, j, ip
  integer :: omp_get_thread_num, tid

  ! I used to allocate 'gtmp' here.

  do r = 1, cfgRBins
    !$omp PARALLEL DEFAULT( none ) &
    !$omp PRIVATE( ip, i, j, tid ) &
    !$omp SHARED( r, xBins, zBins, histCosThBins, histPhiBins )
    allocate( gtmp(4,0:histCosThBins+1,0:histPhiBins+1) )
    tid = omp_get_thread_num()  !debug
    print*, 'test', tid, histCosThBins, histPhiBins, size(gtmp)
    !$omp DO SCHEDULE( guided )
    do ip = 1, (xBins*zBins)
        call subroutine_where_i_alter_gtmp(...)
            ...code to be executed in parallel using gtmp...
    end do !ip
    !$omp END DO
    !$omp END PARALLEL
end do !r
end subroutine compute_avg_force

Итак, проблема заключается в том, что мне нужно, чтобы все потоки были активными (т.е. в параллельной области), чтобы надлежащим образом инициализировать все «версии» gtmp, но моя параллельная область находится внутри цикла иЯ не могу выделить gtmp более одного раза.

Короче говоря, как правильно распределить gtmp в этом коде?Я думал, что мог бы просто сделать еще одну область omp parallel перед циклом и использовать ее для выделения gtmp, но это кажется неуклюжим, поэтому мне интересно, каков "правильный" способ сделать что-то подобное.

Спасибо за помощь!

...