multithreading - 我可以使用 OpenMP 通过单个线程释放共享变量吗?

标签 multithreading fortran openmp shared-memory master-slave

我正在使用OpenMP来并行化代码。根据我要问的问题,这是代码中最重要的部分:

    !$OMP PARALLEL PRIVATE(num_thread) &
    !$OMP SHARED(tasklist_GRAD,threads_list,threads_list_all,tasks_ready_master) &
    !$OMP SHARED(threads_list_part1,nthreads)

    num_thread=OMP_GET_THREAD_NUM() ! le rang du thread 
    nthreads=OMP_GET_NUM_THREADS() ! le nombre de threads



    !Thread Application Master (numero 1)
    if (num_thread==1) then
       do ff=1,3 ! 3 tâches
          if (associated(tasklist_GRAD(ff)%f_ptr) .eqv. .true. ) then ! Si tâche attribuée 
             tasks_ready_master(ff) = tasklist_GRAD(ff) ! égalité de pointeurs 
             tasks_ready_master(ff)%state=STATE_READY
          end if
       end do
    end if
    !$OMP BARRIER

    !Thread Master (numero 0)
    if (num_thread==0) then 

       allocate(threads_list(nthreads-2)) ! liste des threads workers 
       do ff=1,nthreads-2 
          threads_list(ff)=ff+1 ! 2,3,..,nombre de threads-2
       end do

       do ff=1,3,nthreads-2
          if (tasks_ready_master(ff)%state==STATE_READY) then
             threads_list_all(ff:ff+nthreads-3)=threads_list(:)
          end if
       end do
       threads_list_part1=threads_list_all(1:3) ! 3 tâches
       deallocate(threads_list)
    end if

    !$OMP BARRIER

如您所见,threads_list 是一个共享变量。我的问题很简单。 我是否有权通过 1 个单线程取消分配 shared 变量,或者我应该退休 if (num_thread==0) then 以便让所有线程完成此操作线程?

我问这个是因为我收到与内存泄漏相关的错误。

最佳答案

为了回答这个问题,因为共享变量只有一个实例化,它只需要被释放一次 - 但由哪个线程并不重要:

ijb@ijb-Latitude-5410:~/work/stack$ cat omp.f90
Program omp_alloc

  Use omp_lib, Only : omp_get_num_threads, omp_get_thread_num

  Implicit None

  Integer, Dimension( : ), Allocatable :: a

  Integer :: ith
  Integer :: nth
  Integer :: i
  
  Allocate( a( 1:4 ) )
  a = [ ( i, i = 1, 4 ) ]

  !$omp parallel default( none ) shared( a ) private( ith, nth )
  nth = omp_get_num_threads()
  ith = omp_get_thread_num ()
  Write( *, * ) ith, nth, 'a = ', a
  ! Barrier to make sure a is printed by all threads before deallocation
  !$omp barrier
  !$omp single
  Write( *, * ) 'Thread ', ith, ' Deallocating'
  Deallocate( a )
  !$omp end single
  !$omp end parallel

  Write( *, * ) Allocated( a )
  
End Program omp_alloc
ijb@ijb-Latitude-5410:~/work/stack$ gfortran-11 --version
GNU Fortran (GCC) 11.1.0
Copyright © 2021 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ijb@ijb-Latitude-5410:~/work/stack$ gfortran-11 -Wall -Wextra -fcheck=all -O -g -std=f2018 -fopenmp omp.f90 
ijb@ijb-Latitude-5410:~/work/stack$ export OMP_NUM_THREADS=4
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
 Thread            3  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            0  Deallocating
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           4 a =            1           2           3           4
           3           4 a =            1           2           3           4
           1           4 a =            1           2           3           4
           2           4 a =            1           2           3           4
 Thread            2  Deallocating
 F

如果您尝试通过多个线程取消分配,则会出现未定义的行为。在 gfortran 上,至少他通过看起来像是在测试当您尝试释放数组时是否分配数组的竞争条件来体现它自己:

ijb@ijb-Latitude-5410:~/work/stack$ cat omp.f90
Program omp_alloc

  Use omp_lib, Only : omp_get_num_threads, omp_get_thread_num

  Implicit None

  Integer, Dimension( : ), Allocatable :: a

  Integer :: ith
  Integer :: nth
  Integer :: i
  
  Allocate( a( 1:4 ) )
  a = [ ( i, i = 1, 4 ) ]

  !$omp parallel default( none ) shared( a ) private( ith, nth )
  nth = omp_get_num_threads()
  ith = omp_get_thread_num ()
  Write( *, * ) ith, nth, 'a = ', a
  !$omp barrier
  Deallocate( a )
  !$omp end parallel

  Write( *, * ) Allocated( a )
  
End Program omp_alloc
ijb@ijb-Latitude-5410:~/work/stack$ gfortran-11 -Wall -Wextra -fcheck=all -O -g -std=f2018 -fopenmp omp.f90 
ijb@ijb-Latitude-5410:~/work/stack$ export OMP_NUM_THREADS=8
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
           6           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           6           8 a =            1           2           3           4
           0           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
At line 21 of file omp.f90
Fortran runtime error: Attempt to DEALLOCATE unallocated 'a'

Error termination. Backtrace:
#0  0x7fe058962d01 in ???
#1  0x7fe058963849 in ???
#2  0x7fe058963ec6 in ???
#3  0x4012fa in MAIN__._omp_fn.0
    at /home/ijb/work/stack/omp.f90:21
#4  0x7fe0587cb77d in ???
#5  0x7fe058732608 in start_thread
    at /build/glibc-YbNSs7/glibc-2.31/nptl/pthread_create.c:477
#6  0x7fe058657292 in ???
#7  0xffffffffffffffff in ???
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
           6           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           6           8 a =            1           2           3           4
           0           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           6           8 a =            1           2           3           4
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           6           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
 F
ijb@ijb-Latitude-5410:~/work/stack$ ./a.out
           0           8 a =            1           2           3           4
           1           8 a =            1           2           3           4
           3           8 a =            1           2           3           4
           2           8 a =            1           2           3           4
           4           8 a =            1           2           3           4
           7           8 a =            1           2           3           4
           5           8 a =            1           2           3           4
           6           8 a =            1           2           3           4
At line 21 of file omp.f90
Fortran runtime error: Attempt to DEALLOCATE unallocated 'a'

Error termination. Backtrace:
#0  0x7fef41e85d01 in ???
#1  0x7fef41e86849 in ???
#2  0x7fef41e86ec6 in ???
#3  0x4012fa in MAIN__._omp_fn.0
    at /home/ijb/work/stack/omp.f90:21
#4  0x7fef41cee77d in ???
#5  0x7fef41c55608 in start_thread
    at /build/glibc-YbNSs7/glibc-2.31/nptl/pthread_create.c:477
#6  0x7fef41b7a292 in ???
#7  0xffffffffffffffff in ???

关于multithreading - 我可以使用 OpenMP 通过单个线程释放共享变量吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67983417/

相关文章:

fortran - 数组中派生类型变量的 Maxval

python - f2py 在 Fortran 中的 Python 回调函数中使用数组

parallel-processing - LSF 中的混合 MPI/OpenMP

c++ - Mac 上的超线程——没有提供太多加速

c++ - 原子访问 C++11 和 OpenMP 中的非原子内存位置?

java - JMM 在实践中

c++ - 使用 Mutex 的线程同步

algorithm - 计算 Pi 的贝拉德算法

multithreading - 并发调用 `Wait()`的 `sync.Cond`方法,安全吗?

java.lang.IllegalArgumentException : im == null! 错误