我喜欢这样做:
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 * *
答案 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,取决于您用于下限的内容)。
并行构造(仅)内的私有可分配数组的显式分配也可以是一个选项。