【发布时间】:2018-03-18 08:20:57
【问题描述】:
我使用gfortran -O -mcmodel=medium test.f90 -lfftw3_omp -lfftw3 -lm -qopenmp 编译以下程序,并将fftw3.f 添加到/usr/lib。我使用ulimit -s unlimited to run ./out,因为否则会出现堆栈溢出(Why Segmentation fault is happening in this openmp code?)。
program main
Implicit none
include 'omp_lib.h'
include 'fftw3.f'
Integer i, j, k, iter
Integer,Parameter :: Nx =381
Integer,Parameter :: Ny =129
Integer,Parameter :: Nz =129
Integer, parameter :: N1 = Ny-1
Integer, parameter :: N2 = Nz-1
double precision in
dimension in(N1,N2)
double complex out
dimension out(N1/2 + 1, N2)
integer*8 plan
real*8 U(-2:Nx+2,-2:Ny+2,-2:Nz+2)
real*8 V(-2:Nx+2,-2:Ny+2,-2:Nz+2)
real*8 W(-2:Nx+2,-2:Ny+2,-2:Nz+2)
Real*8 ky_vis(0:Ny)
Real*8 kz_vis(0:Nz)
Complex*16 F_F1(-2:Nx+2,-2:Ny+2,-2:Nz+2)
Real*8,Parameter :: pi = 3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825d0
Real*8,Parameter :: Ly = 1.0d0 * 2.0d0 * pi
Real*8,Parameter :: Lz = 1.0d0 * 2.0d0 * pi
Real*8 c1_Nfft
Integer,Parameter :: NyFFT = (Ny-1 + 2) / 2
c1_Nfft = 1.0d0 / dsqrt( Dble(Ny-1) * Dble(Nz-1) )
U= reshape((/(i, i=1,(Nx+5)*(Ny+5)*(Nz+5))/),shape(U))
V = reshape((/(i, i=1,(Nx+5)*(Ny+5)*(Nz+5))/),shape(V))
W = reshape((/(i, i=1,(Nx+5)*(Ny+5)*(Nz+5))/),shape(W))
!$OMP PARALLEL DO PRIVATE(j) SHARED(ky_vis)
Do j = 1, (Ny-1)/2+1
ky_vis(j) = ( 2.0d0 * pi /Ly ) * Dble( j-1 )
End Do
!$OMP End PARALLEL DO
!$OMP PARALLEL DO PRIVATE(j) SHARED(ky_vis)
Do j=(Ny-1)/2+2,Ny-1
ky_vis(j) = ( 2.0d0 * pi /Ly ) * Dble((Ny-1)-(j-1))
end do
!$OMP End PARALLEL DO
!$OMP PARALLEL DO PRIVATE(k) SHARED(kz_vis)
Do k = 1, (Nz-1)/2+1
kz_vis(k) = ( 2.0d0 * pi /Lz ) * Dble( k-1 )
End Do
!$OMP End PARALLEL DO
!$OMP PARALLEL DO PRIVATE(j) SHARED(ky_vis)
Do k=(Nz-1)/2+2,Nz-1
kz_vis(k) = ( 2.0d0 * pi /Lz ) * Dble((Nz-1)-(k-1))
end do
!$OMP End PARALLEL DO
!-----------FFTW----------------
Do i = 1, Nx-1 ! --- \8F\87\95ϊ\B7 ---
! !$OMP PARALLEL DO PRIVATE(i,j,k) SHARED(Real_F1)
Do k = 1, Nz-1
Do j = 1, Ny-1
in(j,k) = U(i,j,k)
End Do; End Do
! !$OMP END PARALLEL DO
call dfftw_plan_dft_r2c_2d(plan,N1,N2,in,out,FFTW_ESTIMATE)
call dfftw_execute_dft_r2c(plan, in, out)
call dfftw_destroy_plan(plan)
! !$OMP PARALLEL DO PRIVATE(j,k) SHARED(F_F1)
Do j = 1, NyFFT
Do k = 1, Nz-1
F_F1(i,j,k) = out(j,k) * c1_Nfft
End Do; End Do
! !$OMP END PARALLEL DO
End Do
!-----------IFFTW----------------
Do i = 1, Nx-1 !
Do j = 1, NyFFT
Do k = 1, Nz-1
out(j,k) = - ( ky_vis(j) * ky_vis(j) &
+ kz_vis(k) * kz_vis(k) ) * F_F1(i,j,k)
End Do; End Do
call dfftw_plan_dft_c2r_2d(plan,N1,N2,out,in,FFTW_ESTIMATE)
call dfftw_execute_dft_c2r(plan, out, in)
call dfftw_destroy_plan(plan)
! !$OMP PARALLEL DO PRIVATE(j,k) SHARED(ddUdx)
Do k = 1, Nz-1
Do j = 1, Ny-1
U(i,j,k) = U(i,j,k) + in(j,k) * c1_Nfft
End Do; End Do
! !$OMP END PARALLEL DO
End Do
end program
我用system_clock查看了FFTW的执行时间,发现其实计算太慢了。有没有更好的方法让它运行得更快?我在Ubuntu 17.04上使用gfortran,CPU是AMD1950x,内存64G。
【问题讨论】:
-
欢迎您,请拨打tour 并阅读How to Ask。它是如何失败的?任何错误信息?错误的结果?怎么错了?你如何编译代码?用哪个编译器?请edit问题提供更多信息。
-
另外,我们需要知道剩下的代码,知道 Nx 和 Ny 的值,见minimal reproducible example。尝试使 Nx 和 Ny 非常小,如果它仍然崩溃,请报告。尝试使您的数组可分配并在它仍然崩溃时报告。
-
虽然 Hristo 在他有时冗长且非常详细的回答中总是建议使用堆栈,但我推荐
allocatable数组。 -
对不起,我只是想知道有没有办法使用多线程fftw,因为我的一个线程计算fftw真的很慢。试了几个错误的方法,所以没有提交。 NX=1000,纽约=300,新西兰=300。
-
我在 ubuntu 17.04 上使用 gfortran