/* --------------------------------------------------------------- * MPI - Two-Dimensional Fast Fourier Transform - C Version * FILE: mpi_2dfft.c * OTHER FILES: mpi_2dfft.h * DESCRIPTION: The image originates on a single processor (SOURCE_PROCESSOR). * This image, a[], is distributed by rows to all other processors. Each * processor then performs a one-dimensional FFT on the rows of the image * stored locally. The image is then transposed using the MPI_Alltoall() * routine; this partitions the intermediate image by columns. Each * processor then performs a one-dimensional FFT on the columns of the * image. Finally, the columns of the image are collected back at the * destination processor and the output image is tested for correctness. * * Input is a 512x512 complex matrix. The input matrix is initialized with * a point source. Output is a 512x512 complex matrix that overwrites * the input matrix. Timing and Mflop results are displayed following * execution. * * A straightforward unsophisticated 1D FFT kernel is used. It is * sufficient to convey the general idea, but be aware that there are * better 1D FFTs available on many systems. * * AUTHOR: George Gusciora * LAST REVISED: 06/08/96 Blaise Barney * --------------------------------------------------------------- */ #include #include #include #include #include #include #include "mpi_2dfft.h" #define IMAGE_SIZE 512 #define NUM_CELLS 4 #define IMAGE_SLICE (IMAGE_SIZE / NUM_CELLS) #define SOURCE_PROCESSOR 0 #define DEST_PROCESSOR SOURCE_PROCESSOR int numtasks; /* Number of processors */ int taskid; /* ID number for each processor */ mycomplex a[IMAGE_SIZE][IMAGE_SIZE]; /* input matrix: complex numbers */ mycomplex a_slice[IMAGE_SLICE][IMAGE_SIZE]; mycomplex a_chunks[NUM_CELLS][IMAGE_SLICE][IMAGE_SLICE]; mycomplex b[IMAGE_SIZE][IMAGE_SIZE]; /* intermediate matrix */ mycomplex b_slice[IMAGE_SIZE][IMAGE_SLICE]; mycomplex b_chunks[NUM_CELLS][IMAGE_SLICE][IMAGE_SLICE]; mycomplex *collect; mycomplex w_common[IMAGE_SIZE/2]; /* twiddle factors */ struct timeval etime[10]; int checkpoint; float dt[10], sum; int main(argc,argv) int argc; char *argv[]; { int num_procs, rc; int cell, i, j, n, nx, logn, errors, sign, flops; float mflops; num_procs = atoi(getenv("MP_PROCS")); if (num_procs != NUM_CELLS) { printf("Error: NUM_CELLS is %d, MP_PROCS is %d\n", NUM_CELLS, num_procs); exit(1); } checkpoint=0; /* Initialize MPI environment and get task's ID and number of tasks * in the partition. */ rc = MPI_Init(&argc,&argv); rc|= MPI_Comm_size(MPI_COMM_WORLD,&numtasks); rc|= MPI_Comm_rank(MPI_COMM_WORLD,&taskid); if (rc != 0) printf ("error initializing MPI and obtaining task ID information\n"); else printf ("MPI task ID = %d\n", taskid); n = IMAGE_SIZE; /* compute logn and ensure that n is a power of two */ nx = n; logn = 0; while(( nx >>= 1) > 0) logn++; nx = 1; for (i=0; i n*sign+EPSILON || b[i][j].r < n*sign-EPSILON || b[i][j].i > n*sign+EPSILON || b[i][j].i < n*sign-EPSILON) { printf("[%d][%d] is %f,%f should be %f\n", i, j, b[i][j].r, b[i][j].i, (float) n*sign); errors++; } sign *= -1; } } if (errors) { printf("%d errors!!!!!\n", errors); exit(0); } } /********** if (taskid == DEST_PROCESSOR) { for(i=0;i> 1; i0++) { for (i1 = 0; i1 < n; i1 += incrvec) { f0 = data[i0+i1 + incrvec/2].r * w_common[i0<>1; while (k <= j) { j -= k; k >>= 1; } j += k; } }