Advertisement
bhavyagoyal

Assignment 6 Parallel FFT

Nov 4th, 2015
3,404
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <math.h>
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <sys/time.h>
  5. #include <time.h>
  6. #include <mpi.h>
  7. #include "evaluate.h"
  8.  
  9. void fftCompute(int size, int rank, int NPerProc, float *inputFFTPerProc, float *outputFFTPerProc,  float *tempBuffer);
  10.  
  11. int main(int argc, char *argv[])
  12. {
  13.     MPI_Init(&argc, &argv);
  14.     int size, rank;
  15.     MPI_Comm_size(MPI_COMM_WORLD, &size);
  16.     MPI_Comm_rank(MPI_COMM_WORLD, &rank);
  17.  
  18.     int evalFlag = atoi(argv[4]);
  19.     if(evalFlag == 1){
  20.        
  21.         int N = atoi(argv[1]);
  22.         int NPerProc = N/size;
  23.         float *inputFFTPerProc = malloc(NPerProc*sizeof(float));
  24.         float *outputFFTPerProc = malloc(2*NPerProc*sizeof(float));
  25.         float *tempBuffer = malloc(2*NPerProc*sizeof(float));   // Only use this space for temporary Storage
  26.  
  27.         // Read part of the input file corresponding to the rank of the processor
  28.         myInit(argc, argv, N, NPerProc, rank, inputFFTPerProc);
  29.  
  30.         fftCompute(size, rank, NPerProc, inputFFTPerProc, outputFFTPerProc, tempBuffer);
  31.  
  32.         double tolerance = pow(10.0,-5);
  33.         int check = checkCorrectness(rank, N, NPerProc, outputFFTPerProc, tolerance);
  34.  
  35.         if(rank != 0)
  36.             MPI_Send(&check,1,MPI_INT,0,0,MPI_COMM_WORLD);
  37.  
  38.         // Check overall output of the FFT computation
  39.         if(rank == 0){
  40.             int proc, correctCount=0;
  41.             for(proc=1;proc<size;proc++){
  42.                 int check1;
  43.                 MPI_Recv(&check1, 1, MPI_INT, proc, 0, MPI_COMM_WORLD,MPI_STATUS_IGNORE);
  44.                 correctCount = correctCount+check1;
  45.             }
  46.             correctCount = correctCount+check;
  47.             if (correctCount == size) printf("%s\n","Correct");
  48.             else printf("%s\n","Incorrect");   
  49.         }
  50.     }
  51.     else{
  52.         //////////////////////////////////////////////////////////////////////
  53.         /////////  Optional code for defining your own data and test /////////
  54.        // NOTE : You will to unable to use checkCorrectness(..) function to
  55.        //        check the correctness of your implementation
  56.  
  57.         printf("Run Part\n");
  58.         //////////////////////////////////////////////////////////////////////
  59.     }  
  60.     MPI_Finalize();
  61.    return 0;
  62. }
  63.  
  64. typedef struct complex {
  65.    float a,b;
  66. }complex;
  67.  
  68. complex compa(complex a, complex b){
  69.    complex ans;
  70.    ans.a = a.a + b.a;
  71.    ans.b = a.b + b.b;
  72.    return ans;
  73. }
  74.  
  75. complex comps(complex a, complex b){
  76.    complex ans;
  77.    ans.a = a.a - b.a;
  78.    ans.b = a.b - b.b;
  79.    return ans;
  80. }
  81.  
  82. complex compm(complex c, complex d){
  83.    complex ans;
  84.    ans.a = c.a*d.a - c.b*d.b;
  85.    ans.b = c.a*d.b + c.b*d.a;
  86.    return ans;
  87. }
  88.  
  89.  
  90. complex nthroot(int k, int n){
  91.    complex ans;
  92.    float arg = (-2.0 * (M_PI) * k )/ (1.0*n);
  93.    ans.a = cos(arg);
  94.    ans.b = sin(arg);
  95.    return ans;
  96. }
  97.  
  98. void dftrecur(complex *a, complex* b, int n){
  99.    if(n==1){return;}
  100.    complex *even;
  101.    complex *odd;
  102.    even = b;
  103.    odd = b + n/2;
  104.    
  105.    int it;
  106.    for(it=0;it<(n/2);it++){
  107.        even[it] = a[2*it];
  108.        odd[it] = a[2*it+1];
  109.    }
  110.    
  111.    memcpy(a,even, n/2 * sizeof(complex));
  112.    memcpy(a+n/2, odd, n/2 * sizeof(complex));
  113.    dftrecur(a,b,n/2);
  114.    dftrecur(a + n/2,b + n/2,n/2);
  115.  
  116.    for(it=0;it<n;it++){
  117.        complex omega = nthroot(it%(n/2),n);
  118.        if(it<n/2){
  119.            complex temp1 = compm(omega, a[it+(n/2)]);
  120.            b[it] = compa(a[it],temp1);
  121.        }
  122.        else{
  123.            complex temp1 = compm(omega, a[it]);
  124.            b[it] = comps(a[it-n/2],temp1);
  125.        }
  126.    }
  127.    
  128.    memcpy(a,b,n*sizeof(complex));
  129. }
  130.  
  131. void ordering(int* arr , int n){
  132.    if(n<=2){return;}
  133.    int even[n/2],odd[n/2];
  134.  
  135.    int i=0;
  136.    for(i=0;i<n/2;i++){
  137.        even[i] = arr[2*i];
  138.        odd[i] = arr[2*i+1];
  139.    }
  140.  
  141.    memcpy(arr,even, n/2 * sizeof(int));
  142.    memcpy(arr+n/2, odd, n/2 * sizeof(int));
  143.  
  144.    ordering(arr,n/2);
  145.    ordering(arr+n/2,n/2);
  146.    return;
  147. }
  148.  
  149. void reorder(int n, float* inputFFTPerProc, float* outputPerProc, float* tempBuffer){
  150.    // printf("Size%d\n",n);
  151.    if(n==2){
  152.        outputPerProc[0] = inputFFTPerProc[0];
  153.        outputPerProc[1] = inputFFTPerProc[1];
  154.        return;
  155.    }
  156.    if(n==1){
  157.        outputPerProc[0] = inputFFTPerProc[0];
  158.        return;
  159.    }
  160.    memcpy(tempBuffer, inputFFTPerProc, n*sizeof(float));
  161.    int i;
  162.    for(i=0;i<n/2;i++){
  163.        inputFFTPerProc[i] = tempBuffer[2*i];
  164.        inputFFTPerProc[i+n/2] = tempBuffer[2*i+1];
  165.    }
  166.    reorder(n/2,inputFFTPerProc, outputPerProc, tempBuffer);
  167.    reorder(n/2,inputFFTPerProc+n/2, outputPerProc+n/2, tempBuffer);
  168. }
  169.  
  170. void fftCompute(int size, int rank, int NPerProc, float *inputFFTPerProc, float *outputPerProc,  float *tempBuffer){
  171.  
  172. // Please add your code for FFT Computation within the provided section //
  173. // Store your output in the outputArray with even index for real and odd index for
  174. // imaginary part
  175. ////////////////////////////////////////////////////////////////////////////////////////////
  176.  
  177.  
  178.    // Code for parallel Execution //
  179.    int it, j;
  180.    int arr[size];
  181.    for(it=0;it<size;it++){
  182.        arr[it] = it;
  183.    }
  184.    ordering(arr,size);
  185.    int numiter = NPerProc/size;
  186.  
  187.    // Dividing the data in order of processor;
  188.    for(it=0;it<numiter;it++){
  189.        for(j=0;j<size;j++){
  190.            int p = numiter*arr[j] + it;
  191.            outputPerProc[2*p] = inputFFTPerProc[it*size + j];
  192.            outputPerProc[2*p+1] = 0.0;
  193.        }
  194.    }
  195.  
  196.    MPI_Alltoall(MPI_IN_PLACE, 2*(NPerProc/size), MPI_FLOAT, outputPerProc, 2*NPerProc/size, MPI_FLOAT, MPI_COMM_WORLD);
  197.    //Solve serially for the data on same processor
  198.    dftrecur(outputPerProc, tempBuffer, NPerProc);
  199.  
  200.    //Now combine the output in log(size) steps like the binary tree
  201.    int numproc=1;
  202.    MPI_Status stat;
  203.    complex omega;
  204.    complex temp1, temp2;
  205.    while(numproc!=size){
  206.        int Nprime = numproc*2*NPerProc;
  207.        //Two cases for the left and right child
  208.        if(rank%(2*numproc) >=numproc){
  209.             MPI_Recv(tempBuffer, 2*NPerProc, MPI_FLOAT, rank-numproc, 0, MPI_COMM_WORLD, &stat);
  210.             MPI_Send(outputPerProc, 2*NPerProc, MPI_FLOAT, rank-numproc, 0, MPI_COMM_WORLD);
  211.             for(it=0;it<NPerProc;it++){
  212.                omega = nthroot(((rank-numproc)%numproc)*NPerProc+it,  Nprime);
  213.                temp2 = (complex){outputPerProc[2*it], outputPerProc[2*it+1]};
  214.                temp1 = (complex){tempBuffer[2*it], tempBuffer[2*it+1]};
  215.                temp2 = compm(omega, temp2);
  216.                temp1 = comps(temp1,temp2);
  217.                outputPerProc[2*it] = temp1.a;
  218.                outputPerProc[2*it+1] = temp1.b;
  219.            }
  220.        }
  221.        else{
  222.            MPI_Send(outputPerProc, 2*NPerProc, MPI_FLOAT, rank+numproc, 0, MPI_COMM_WORLD);
  223.            MPI_Recv(tempBuffer, 2*NPerProc, MPI_FLOAT, rank+numproc, 0, MPI_COMM_WORLD, &stat);
  224.            for(it=0;it<NPerProc;it++){
  225.                omega = nthroot((rank%numproc)*NPerProc+it, Nprime);
  226.                temp1 = (complex){outputPerProc[2*it], outputPerProc[2*it+1]};
  227.                temp2 = (complex){tempBuffer[2*it], tempBuffer[2*it+1]};
  228.                temp2 = compm(omega, temp2);
  229.                temp1 = compa(temp1,temp2);
  230.                outputPerProc[2*it] = temp1.a;
  231.                outputPerProc[2*it+1] = temp1.b;
  232.            }
  233.        }
  234.        numproc*=2;
  235.    }
  236.    
  237.    
  238.    ///////// Serial Code ////////////
  239.    // float *compOutput;
  240.    // float *compOutput2;
  241.    // if(rank==0){
  242.     //      compOutput = (float *)malloc(2*NPerProc*size*sizeof(float));
  243.     //  compOutput2 = (float *)malloc(2*NPerProc*size*sizeof(float));
  244.    // }
  245.    // MPI_Gather(inputFFTPerProc, NPerProc, MPI_FLOAT, compOutput2, NPerProc, MPI_FLOAT,0, MPI_COMM_WORLD);
  246.    // int i;
  247.    // int n = NPerProc*size;
  248.    // if(rank==0){
  249.    //     for(i=0;i<n;i++){
  250.    //         compOutput[2*i] = compOutput2[i];
  251.    //         compOutput[2*i+1] = 0.0;
  252.    //     }
  253.    // }
  254.    // if(rank==0){
  255.    //     dftrecur(compOutput, compOutput2, n);
  256.    // }
  257.    // MPI_Scatter(compOutput,2*NPerProc, MPI_FLOAT, outputPerProc, 2*NPerProc, MPI_FLOAT, 0, MPI_COMM_WORLD);
  258.    return;
  259.  
  260.  
  261. ////////////////////////////////////////////////////////////////////////////////////////////
  262. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement