Почему доступ к переменной threadprivate вызывает ошибку сегментации? - PullRequest
1 голос
/ 06 июня 2019

Я изменяю существующий код на Фортране, который использует библиотеку openmp.Исходная версия этого кода прекрасно работает параллельно.

Я получаю ошибку сегментации, когда к многопоточному запуску обращаются к определенной переменной (я проверял, устанавливая флаги во всем коде).Этот массив определяется как выделяемый, затем как threadprivate, а затем размещается, в то время как в исходной версии он не является размещаемым, и его размер устанавливается немедленно.Я изменил эту часть из-за рабочего плана, который мне дали.

Вот базовый фрагмент кода, который воспроизводит ошибку.Переменная guilty - это массив, который называется здесь "var".

program testparallel
  use omp_lib
  implicit none
  integer :: thread_id, thread_num
  integer :: i,N
  integer,dimension(:),allocatable,save :: var

  !$omp threadprivate(var)

  N = 20
  allocate(var(5))

  !$omp parallel default(shared) private(thread_id)

  thread_id  = omp_get_thread_num()
  thread_num = omp_get_num_threads()
  write(*,*)'Parallel execution on ',thread_num, ' Threads'

  !$omp do

  do i=1,N
    var = 0
    write(*,*) thread_id,i
  end do

  !$omp end do
  !$omp end parallel

end program testparallel

Так более или менее структурирован исходный код, я не изменял эту часть напрямую.var инициализируется в цикле, и, согласно входным данным, его значения позже используются другими подпрограммами.

Это трассировка ошибки, которую я получил:

 Parallel execution on            2  Threads
           0           1
           0           2
 Parallel execution on            2  Threads
           0           3
           0           4
           0           5

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.
           0           6

Backtrace for this error:
           0           7
           0           8
           0           9
           0          10
#0  0x7F0149194697
#1  0x7F0149194CDE
#2  0x7F014824E33F
#3  0x400FB2 in MAIN__._omp_fn.0 at testparallel.F90:?
#4  0x7F0148C693C4
#5  0x7F01485ECDD4
#6  0x7F0148315F6C
#7  0xFFFFFFFFFFFFFFFF

Segfault непроисходит, если я не определяю var как выделяемый, но сразу определяю его размер (как в исходном коде).Если я выделю его перед тем, как установить его как threadprivate, я получу ошибку компиляции.

Как можно избежать этой ошибки, но сохранить var как выделяемую (что необходимо)?

РЕДАКТИРОВАТЬ: я исправил описаниеоригинального кода.

1 Ответ

3 голосов
/ 07 июня 2019

Ваша проблема связана с тем, что, хотя ваш выделяемый массив var объявлен threadprivate, он размещен только в непараллельной части кода.Поэтому, находясь в параллельном разделе, только главный поток может безопасно получить доступ к массиву.

Очень простое решение - заключить выделение массива (и последующее перераспределение) в раздел parallel, как этот:

!$omp parallel
allocate(var(5))
!$omp end parallel
...