1

我喜欢这样做:

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 *

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

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

* 检测到 glibc./a.out:双重释放或损坏(输出):0x00002b22a0c016f0 * *

4

3 回答 3

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

请注意,我删除了您对模块的使用,因为它是不必要的。您有一个包含子例程的外部模块,因此只需将其设为外部子例程即可。另外,我将您的矩阵更改为静态分配。case 语句是 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

我刚刚删除了它周围的模块外壳并更改了一些变量名。Fortran 不区分大小写,所以不要用大写字母和自始至终重复它来折磨自己。

我编译了这个

ifort -o diffeq diffeq.f90 电场.f90 -openmp

并与

./diffeq > 输出

捕捉程序呕吐 0 并查看我使用了多少线程:

(0.000000000000000000000E + 000,0.000000000000000000000000000000 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.000000000000000000000E + 000,0.000000000000000000000000000000 0.000000000000000E+000) (0.000000000000000E+000,0.000000000000000E+000)

希望这可以帮助!

于 2013-02-20T16:09:54.470 回答
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
于 2013-02-20T16:42:57.873 回答
0

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

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

(仅)并行结构内的私有可分配数组的显式分配也可能是一种选择。

于 2013-02-20T21:12:38.297 回答