使用openmp和可分配数组在fortran中循环

时间:2013-02-19 11:16:52

标签: fortran openmp fortran90

我喜欢这样做:

program main
  implicit none
  integer l
  integer, allocatable, dimension(:) :: array

  allocate(array(10))

  array = 0

  !$omp parallel do private(array)
  do l = 1, 10
    array(l) = l
  enddo
  !$omp end parallel do

  print *, array

  deallocate(array)

end

但是我遇到了错误消息:

  

*检测到glibc * ./a.out:munmap_chunk():指针无效:0x00007fff25d05a40 *

根据英特尔论坛的some discussions,这似乎是ifort中的一个错误,但应该在我使用的版本(11.1.073 - Linux)中解决。这是我的代码的大规模缩小版!遗憾的是,我不能使用静态数组来解决这个问题。

如果我将打印件放入循环中,我会收到其他错误:

  

*检测到glibc ./a.out:双重免费或损坏(退出):0x00002b22a0c016f0 * *

3 个答案:

答案 0 :(得分:1)

我刚用ifort和openmp运行你的代码并且它喷出了0d0。我不得不手动退出执行。你的预期产量是多少?我不是不必要地动态分配数组的忠实粉丝。你知道你要分配你的矩阵是什么,所以只需要制作参数并静态地完成它。我会搞砸一些东西并在几个中编辑这个响应。

好的,所以这是我的编辑:

  program main
  implicit none

  integer :: l, j
  integer, parameter :: lmax = 15e3
  integer, parameter :: jmax = 25
  integer, parameter :: nk = 300
  complex*16, dimension(9*nk) :: x0, xin, xout
  complex*16, dimension(lmax) :: e_pump, e_probe
  complex*16 :: e_pumphlp, e_probehlp
  character*25 :: problemtype
  real*8 :: m

  ! OpenMP variables
  integer :: myid, nthreads, omp_get_num_threads, omp_get_thread_num

  x0 = 0.0d0

  problemtype = 'type1'
  if (problemtype .ne. 'type1') then
     write(*,*) 'Problem type not specified. Quitting'
     stop
  else
     ! Spawn a parallel region explicitly scoping all variables
     !$omp parallel 
        myid = omp_get_thread_num()
        if (myid .eq. 0) then
           nthreads = omp_get_num_threads()
           write(*,*) 'Starting program with', nthreads, 'threads'
        endif

        !$omp do private(j,l,m,e_pumphlp,e_probehlp,e_pump,e_probe)
        do j = 1, jmax - 1
           do l = 1, lmax

              call electricfield(0.0d0, 0.0d0, e_pumphlp, &
                                 e_probehlp, 0.0d0)
              !   print *, e_pumphlp, e_probehlp

              e_pump(l) = e_pumphlp
              e_probe(l) = e_probehlp
              print *, e_pump(l), e_probe(l)

           end do
        end do
     !$omp end parallel
  end if

  end program main

注意我删除了你对模块的使用,因为它是不必要的。你有一个包含子程序的外部模块,所以只需将它作为一个外部子程序。另外,我将您的矩阵更改为静态分配。案例陈述是if语句的一种奇特且昂贵的版本。你是15e3 * 25倍而不是一次(昂贵),所以我把它们移到了外面。我改变了OpenMP调用,但只是在语义上。我给了你一些输出,以便你知道OpenMP实际上在做什么。

这是新的子程序:

  subroutine electricfield(t, tdelay, e_pump, e_probe, phase)
  implicit none

  real*8, intent(in) :: t, tdelay
  complex*16, intent(out) :: e_pump, e_probe
  real*8, optional, intent (in) :: phase

  e_pump = 0.0d0
  e_probe = 0.0d0

  return

  end subroutine electricfield

我刚刚移除了它周围的模块shell并更改了一些变量名称。 Fortran不区分大小写,所以不要通过上限和不得不重复它来折磨自己。

我用

编译了这个
  

ifort -o diffeq diffeq.f90 electricfield.f90 -openmp

并用

运行
  

./ diffeq>输出

捕获程序呕吐0并查看我使用的线程数:

  

(0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)
  用32个线程启动程序
  (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)   (0.000000000000000E + 000,0.000000000000000E + 000)

希望这有帮助!

答案 1 :(得分:1)

我没有收到您遇到的错误,但您在OpenMP调用中对数组进行私有化存在问题。

[mjswartz@666-lgn testfiles]$ vi array.f90  
[mjswartz@666-lgn testfiles]$ ifort -o array array.f90 -openmp  
[mjswartz@666-lgn testfiles]$ ./array 
           0           0           0           0           0           0
           0           0           0           0  
[mjswartz@666-lgn testfiles]$ vi array.f90  
[mjswartz@666-lgn testfiles]$ ifort -o array array.f90 -openmp  
[mjswartz@666-lgn testfiles]$ ./array 
           1           2           3           4           5           6
           7           8           9          10

首先运行私有数组,第二运行没有。

  program main
  implicit none

  integer l
  integer, allocatable, dimension(:) :: array

  allocate(array(10))

  !$omp parallel do 
  do l = 1, 10
    array(l) = l
  enddo

  print*, array

  deallocate(array)

  end program main

答案 2 :(得分:0)

您似乎遇到了与OpenMP 3.0实现相关的编译器错误。

如果无法更新编译器,则需要更改方法。有几个选项 - 例如,您可以使可分配的数组共享,将它们的等级增加一个,并让一个线程分配它们,使得额外维度的范围是团队中的工作者数量。然后,对这些数组的所有后续引用都需要具有该额外等级的下标为omp团队编号(+ 1,取决于您用于下限的内容)。

并行构造(仅)内的私有可分配数组的显式分配也可以是一个选项。