我想构建一个2D MPI并行光谱微分代码。 以下代码似乎对x衍生工作正常,无论是串行还是并行:
alloc_local = fftw_mpi_local_size_2d(N0,N1,MPI_COMM_WORLD,&local_n0, &local_0_start);
fplan_u = fftw_mpi_plan_dft_2d(N0,N1,ptr_u,uhat,MPI_COMM_WORLD,FFTW_FORWARD,FFTW_ESTIMATE);
bplan_x = fftw_mpi_plan_dft_2d(N0,N1,uhat_x,ptr_ux,MPI_COMM_WORLD,FFTW_BACKWARD,FFTW_ESTIMATE);
ptr_u = fftw_alloc_real(alloc_local);
ptr_ux = fftw_alloc_real(alloc_local);
uhat = fftw_alloc_complex(alloc_local);
uhat_x = fftw_alloc_complex(alloc_local);
fftw_execute(fplan_u);
// first renormalize the transform...
for (int j=0;j<local_n0;j++)
for (int i=0;i<N1;i++)
uhat[j*N1+i] /= (double)(N1*local_n0);
// then compute the x-derivative
for (int j=0;j<local_n0;j++)
for (int i=0;i<N1/2;i++)
uhat_x[j*N1+i] = I*pow(i,1)*uhat[j*N1+i]/(double)N0;
for (int j=0;j<local_n0;j++)
for (int i=N1/2;i<N1;i++)
uhat_x[j*N1+i] = -I*pow(N1-i,1)*uhat[j*N1+i]/(double)N0;
fftw_execute(bplan_x);
但是,以下y导数代码仅在串行中有效,而不是并行。
bplan_y = fftw_mpi_plan_dft_2d(N0,N1,uhat_y,ptr_uy,MPI_COMM_WORLD,FFTW_BACKWARD,FFTW_ESTIMATE);
fftw_execute(fplan_u);
for (int j=0;j<local_n0;j++)
for (int i=0;i<N1;i++)
uhat[j*N1+i] /= (double)(N1*local_n0);
if (size == 1){ // in the serial case do this
for (int j=0;j<local_n0/2;j++)
for (int i=0;i<N1;i++)
uhat_y[j*N1+i] = I*pow(j,1)*uhat[j*N1+i]/(double)N0;
for (int j=local_n0/2;j<local_n0;j++)
for (unsigned int i=0;i<N1;i++)
uhat_y[j*N1+i] = -I*pow(N1-j,1)*uhat[j*N1+i]/(double)N0;
} else { // in the parallel case instead do this
for (int j=0;j<local_n0;j++)
for (int i=0;i<N1;i++)
if (rank <(size/2))
uhat_y[j*N1+i] = I*pow(j+local_n0*rank,1)*uhat[j*N1+i]/(double)N0;
else
uhat_y[j*N1+i] = -I*pow(N1-(j+local_n0*rank),1)*uhat[j*N1+i]/(double)N0;
}
fftw_execute(bplan_y);
其中条件表达式if(rank&lt;(size / 2))用于去除目的(因为我正在对实数据进行FFT)。对于y导数,去混合似乎是连续正确编码的,并且对于x导数也是并行编码。 我知道FFTW提供了一系列特定于此主题的函数(fftw_mpi_plan_dft_r2c和... _ c2r),但我还是想使用复杂到复杂的例程,因为将来我可能会考虑复杂的数据。
当然,使用fftw_mpi_plan_transpose来转置数据,采用x导数然后转换回并行工作,但我想避免这种情况,因为将来我计划隐含地解决类似扩散的问题,例如。
uhat[i*N0+j] = fhat[i*N0+j]/(pow((double)i,2)+pow((double)j,2)))
这对于转置计划是不可能的。
编辑:奇怪的是,如果我用3个MPI进程运行上面的代码,例如:
my_rank: 0 alloc_local: 87552 local_n0: 171 local_0_start: 0
my_rank: 1 alloc_local: 87552 local_n0: 171 local_0_start: 171
my_rank: 2 alloc_local: 87040 local_n0: 170 local_0_start: 342
我得到的结果仍然是错误的,但看起来更接近正确的解决方案,而不是我用2,4或8个流程获得的结果。