问题
Consider a 2D transform of the form L x M (column major setup), from a complex array src to a real array tgt. Or , in Fortranese,
complex(C_DOUBLE_COMPLEX), pointer :: src(:,:)
real(8), pointer :: tgt(:,:) .
Corresponding pointers are
type(C_PTR) :: csrc,ctgt .
I would allocate them in the following manner:
! The complex array first
alloc_local = fftw_mpi_local_size_2d(M,L/2+1,MPI_COMM_WORLD,local_M,local_offset1)
csrc = fftw_alloc_complex(alloc_local)
call c_f_pointer(csrc, src, [L/2,local_M])
! Now the real array
alloc_local = fftw_mpi_local_size_2d(2*(L/2+1),M, &
MPI_COMM_WORLD,local_L,local_offset2)
ctgt = fftw_alloc_real(alloc_local)
call c_f_pointer(ctgt, tgt, [M,local_L])
Now, the plan would be created as:
! Create c-->r transform with one transposition left out
plan = fftw_mpi_plan_dft_c2r_2d(M,L,src,tgt, MPI_COMM_WORLD, &
ior(FFTW_MEASURE,FFTW_MPI_TRANSPOSED_OUT))
Finally, the transform would be performed as:
call fftw_mpi_execute_dft_c2r(plan, src, tgt)
However, this prescription does not work. The last call causes a segmentation fault. At first, i thought this might have something to do with how I allocate src and tgt arrays, but playing with different amount of memory allocated to tgt did not give any result. So, I am either doing something really silly, or this is not possible to do at all.
EDIT : MINIMALISTIC COMPILEABLE EXAMPLE
program trashingfftw
use, intrinsic :: iso_c_binding
use MPI
implicit none
include 'fftw3-mpi.f03'
integer(C_INTPTR_T), parameter :: L = 256
integer(C_INTPTR_T), parameter :: M = 256
type(C_PTR) :: plan, ctgt, csrc
complex(C_DOUBLE_COMPLEX), pointer :: src(:,:)
real(8), pointer :: tgt(:,:)
integer(C_INTPTR_T) :: alloc_local, local_M, &
& local_L,local_offset1,local_offset2
integer :: ierr,id
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD,id,ierr)
call fftw_mpi_init()
alloc_local = fftw_mpi_local_size_2d(M,L/2+1, MPI_COMM_WORLD, &
local_M, local_offset1)
csrc = fftw_alloc_complex(alloc_local)
call c_f_pointer(csrc, src, [L/2,local_M])
alloc_local = fftw_mpi_local_size_2d(2*(L/2+1),M, MPI_COMM_WORLD, &
& local_L, local_offset2)
ctgt = fftw_alloc_real(alloc_local)
call c_f_pointer(ctgt, tgt, [M,local_L])
plan = fftw_mpi_plan_dft_c2r_2d(M,L,src,tgt, MPI_COMM_WORLD, &
ior(FFTW_MEASURE, FFTW_MPI_TRANSPOSED_OUT))
call fftw_mpi_execute_dft_c2r(plan, src, tgt)
call mpi_finalize(ierr)
end program trashingfftw
回答1:
And the answer is:
For mpi real transforms, there are only two allowed combinations of transpositions and directions:
- real to complex transform and FFTW_MPI_TRANSPOSED_OUT
- complex to real transform and FFTW_MPI_TRANSPOSED_IN
I have found this while digging inside the fftw3 ver. 3.3.4 code, file "rdft2-problem.c", comment on the line 120.
EDIT:
MINIMAL COMPILABLE AND WORKING EXAMPLE:
program trashingfftw
use, intrinsic :: iso_c_binding
use MPI
implicit none
include 'fftw3-mpi.f03'
integer(C_INTPTR_T), parameter :: L = 256
integer(C_INTPTR_T), parameter :: M = 256
type(C_PTR) :: plan, ctgt, csrc
complex(C_DOUBLE_COMPLEX), pointer :: src(:,:)
real(8), pointer :: tgt(:,:)
integer(C_INTPTR_T) :: alloc_local, local_M, &
& local_L,local_offset1,local_offset2
integer :: ierr,id
call mpi_init(ierr)
call mpi_comm_rank(MPI_COMM_WORLD,id,ierr)
call fftw_mpi_init()
alloc_local = fftw_mpi_local_size_2d(L/2+1,M, MPI_COMM_WORLD, &
local_l, local_offset1)
print *, id, "alloc complex=",alloc_local, local_l
csrc = fftw_alloc_complex(alloc_local)
call c_f_pointer(csrc, src, [M,local_l])
!Caveat: Must partition the real storage according to complex layout, this is why
! I am using M and L/2+1 instead of M, 2*(L/2+1) as it was done in the original post
alloc_local = fftw_mpi_local_size_2d(M,L/2+1, MPI_COMM_WORLD, &
& local_M, local_offset2)
print *, id, "alloc real=",alloc_local, local_m
! Two reals per complex
ctgt = fftw_alloc_real(2*alloc_local)
! Only the first L are relevant, the rest is just dangling space (see fftw3 docs)
!caveat: since the padding is in the first index, the 2d data is laid out non-contiguously
!(L sensible reals, padding, padding, L sensible reals, padding, padding, ....)
call c_f_pointer(ctgt, tgt, [2*(L/2+1),local_m])
plan = fftw_mpi_plan_dft_c2r_2d(M,L,src,tgt, MPI_COMM_WORLD, &
ior(FFTW_MEASURE, FFTW_MPI_TRANSPOSED_IN))
! Should be non-null
print *, 'plan:', plan
src(3,2)=(1.,0)
call fftw_mpi_execute_dft_c2r(plan, src, tgt)
call mpi_finalize(ierr)
end program thrashingfftw
来源:https://stackoverflow.com/questions/24290014/how-to-do-a-fftw3-mpi-transposed-2d-transform-if-possible-at-all