Fortran中的PGI,OpenMP和名单

时间:2013-07-11 13:28:51

标签: fortran openmp pgi

我在尝试使用OpenMP和Portland Group编译器读取Fortran程序中的名单时遇到问题。

我想做的很简单:我在read_namelist区域调用SINGLE子程序,在那里我初始化我要从名单中读取的参数,然后打开,读取,关闭名单。我在名单中读取的参数是threadprivate,我在阅读后将它们传播到其他线程。

虽然它与GNU和英特尔编译器完美配合,但PGI失败了,我无法理解。我没有得到任何错误,但读取参数等于默认参数,而不是我从名单中读取的参数。

这是我想要做的一个例子:

program read_input
  !$ use OMP_LIB
  use params
  implicit none

  integer :: rank=0, nthreads=1

  !$OMP PARALLEL DEFAULT(PRIVATE)
  !$ rank = OMP_GET_THREAD_NUM()
  !$ nthreads = OMP_GET_NUM_THREADS()   
  !$OMP SINGLE 
  print*, 'There is ', nthreads, ' threads running'

  call read_nml
  !$OMP END SINGLE COPYPRIVATE(nx, ny, nz)

  print*, 'Rank: ', rank
  print*, 'nx, ny, nz: ', nx, ny, nz
  !$OMP END PARALLEL   

contains
  subroutine read_nml
    use params
    implicit none
    namelist /input_params/ nx, ny, nz

    call default_parameters
    print*, 'nx, ny, nz (default): ', nx, ny, nz

    open(unit=1, file='input', status='old')
    read(1, input_params)
    close(1)
    print*, 'nx, ny, nz (read): ', nx, ny, nz

    return
  end subroutine read_nml

  subroutine default_parameters
    use params
    implicit none

    nx = 2; ny = 2; nz = 2

    return
  end subroutine default_parameters
end program read_input

模块params非常简单,只包含:

module params
  integer :: nx, ny, nz
  !$OMP THREADPRIVATE(nx, ny, nz)
end module params

使用pgfortran进行编译,这是我得到的输出(有2个线程):

 Start program: read_input
 There is             2  threads running
 nx, ny, nz (default):             2            2            2
 Rank:             0
 nx, ny, nz:             2            2            2
 Rank:             1
 nx, ny, nz:             2            2            2

如果我使用Intel或GNU编译器编译相同的代码(仍然有2个线程):

 Start program: read_input
 There is            2  threads running
 nx, ny, nz (default):            2           2           2
 nx, ny, nz (read):           10          10          10
 Rank:            0
 nx, ny, nz:           10          10          10
 Rank:            1
 nx, ny, nz:           10          10          10

任何想法或提示都将不胜感激!

1 个答案:

答案 0 :(得分:0)

我没有得到确切的理由,但至少我找到了解决方法,使用代码。

如果名单中读取的参数在子程序中是私有的,则可以毫无问题地读取它们;因此取代

call read_nml

通过

call read_nml(nx, ny, nz)

的子程序read_nml
  subroutine read_nml(nx, ny, nz)
    implicit none
    integer :: nx, ny, nz             
    namelist /input_params/ nx, ny, nz

    call default_parameters
    print*, 'nx, ny, nz (default): ', nx, ny, nz

    open(unit=1, file='input', status='old')
    read(1, input_params)
    close(1)
    print*, 'nx, ny, nz (read): ', nx, ny, nz

    return
  end subroutine read_nml

运作良好。我想这又是属性的状态(私有)的问题,但我不明白为什么英特尔和GNU编译器没有问题处理它,而PGI编译器无法处理它。实际上,这就是为什么参数是我的模块中的threadprivate,以防止这种行为。如果有人能给我一个比我更好的答案,我仍然感兴趣!