You are here: Home » The Last Program

The Last Program

Parallel Vector Normalization with MPI

#include <mpi.h>
#include "supercomputing_simplified.hpp"
#include "ScS_functions.cpp"

int main (int argc,char *argv[])
{
    int P_rank, worldsize, rootfordata=-99, i, myturn;
    const int d_size=13;
    int data_array[d_size];
    float bigtot=0.0, sqsubtot=0.0, checklength=0.0;
    float eulength[]={0.0}, data_arrayf[d_size], tempfileforworkf[d_size];

    for (i = 0; i < d_size; i++){ tempfileforworkf[i] = 0.0;}

    MPI_Init(&argc,&argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &P_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &worldsize);
 

    for (i = 0; i < d_size; i++)
        {data_array[i] = i+10*P_rank;data_arrayf[i]=(float)data_array[i];}

    ourmpi_printf(data_array, d_size, P_rank,worldsize,"Process %i's data: ");
    rootfordata = keyb_entry_nonneg_int(P_rank,worldsize,"\nChoose data from a single Process");
    MPI_Bcast(&rootfordata,1,MPI_INT,0,MPI_COMM_WORLD);

    //....................partition and scatter
    int* blocklengths= new int[worldsize];
    int* blockoffsets= new int[worldsize];
    scv_partition(worldsize, d_size,blocklengths,blockoffsets);
    int rcv_count=blocklengths[P_rank];
    MPI_Scatterv(data_arrayf, blocklengths, blockoffsets,
    MPI_FLOAT, tempfileforworkf,rcv_count,
    MPI_FLOAT
,
rootfordata,MPI_COMM_WORLD);

    //..................local sum of squares
    sqsubtot=innerprod(tempfileforworkf,tempfileforworkf,blocklengths[P_rank]);

    // option to print local sum of squares
    ourmpi_printf(&sqsubtot,1,P_rank,worldsize,
     "Sum of squares at Process %d: ");
    MPI_Barrier(MPI_COMM_WORLD);

    //............gather subtotals and extract square root of total........
    int* rcv_singletons= new int[worldsize];
    for (i=0;i<worldsize;i++) {rcv_singletons[i]=1; }
    int* rcv_offsets = new int[worldsize];
    for (i=0;i<worldsize;i++) {rcv_offsets[i]=i;}
    float* subtot = new float[worldsize];
    for (i = 0; i < worldsize; i++){ subtot[i] = 0.0; }

    MPI_Gatherv(&sqsubtot, 1, MPI_FLOAT,
    subtot, rcv_singletons, rcv_offsets,
   
MPI_FLOAT, 0, MPI_COMM_WORLD);


    delete [] rcv_singletons;
    delete [] rcv_offsets;

    if (P_rank==0)
    {
        for (i=0;i<worldsize;i++){bigtot = bigtot + subtot[i];}
        eulength[0]=sqrt(bigtot);
        printf("\nTotal sum of squares %d\n",(int) bigtot);
        printf("Euclidean length of Process %d's data_array %f \n\n",//
        rootfordata,eulength[0]);
    }

    delete []subtot;
    //....broadcast euclidean length and normalize scattered elements....
    MPI_Bcast(eulength, 1, MPI_FLOAT, 0, MPI_COMM_WORLD);

    for (i=0;i<blocklengths[P_rank];i++ )
        {tempfileforworkf[i] = tempfileforworkf[i]/eulength[0];}

    //the printing below is from zero
    //...........gather normalized elements and concatenate...........

    MPI_Gatherv(tempfileforworkf, rcv_count, MPI_FLOAT,
   
data_arrayf, blocklengths, blockoffsets,
   
MPI_FLOAT, 0, MPI_COMM_WORLD);

    delete []blocklengths;
    delete []blockoffsets;
    checklength=innerprod(data_arrayf, data_arrayf, d_size);
    printf_oneP_nobarrier(0, P_rank, data_arrayf, d_size, "Process %d's normalized array:\n", rootfordata);

    if (P_rank==0)
    {
        printf("\n normalized array length check (is it 1?); uses innerprod(): \n %f\n", checklength);
    }

    MPI_Finalize();
    return 0;
}