1

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

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

虽然它在 GNU 和 Intel 编译器上工作得很好,但在 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

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

4

1 回答 1

0

我不明白确切的原因,但至少我找到了一种解决方法,使用代码。

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

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 编译器却无法处理它。实际上,这就是为什么我的模块中的参数是线程私有的,以防止这种行为。如果有人能给我一个比我更好的答案,我仍然有兴趣!

于 2013-07-12T06:26:30.977 回答