/*

 * dotprod.c

 *     Εσωτερικό γινόμενο δύο διανυσμάτων χρησιμοποιώντας MPI

 *  Created on: 31 Οκτ 2011

 *      Author: Kostas Diamantaras

 */

 

 

#include "mpi.h"

#include <stdio.h>

#include <string.h>

#include <math.h>

 

int main(int argc, char **argv) {

       int procs, rank;

       double x[1000], y[1000];

       double local_x[1000], local_y[1000];

       int i, n;

       int partSize;

       FILE *fid;

       char *sFileName, defaultName[] = "dotprod.dat";

       double local_prod, prod, trueProd;

 

       MPI_Init(&argc, &argv);

       MPI_Comm_size(MPI_COMM_WORLD, &procs);

       MPI_Comm_rank(MPI_COMM_WORLD, &rank);

 

       if (rank==0) {

              if (argc==2) {

                     /* The filename is the first argument of the program */

                     sFileName = argv[1];

              } else {

                     /* Default file name */

                     sFileName = defaultName;

              }

              printf("Opening file: %s\n", sFileName);

              fid = fopen(sFileName,"r");

              /* Read vector dimensions */

              fscanf(fid, "%d", &n);

              printf("Vector dimensions: %d\n", n);

              /* Read vector x */

              for (i=0; i<n; i++) {

                     fscanf(fid, "%lf", &(x[i]));

              }

              /* Read vector y */

              for (i=0; i<n; i++) {

                     fscanf(fid, "%lf", &(y[i]));

              }

              /* Read true inner product */

              fscanf(fid, "%lf", &trueProd);

              fclose(fid);

       }      /* end if rank == 0 */

 

       /* Broadcast n */

       MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);

 

       /* Partition x[] and y[] into "procs"-many parts

        * of size ceil(n / procs) each.

        */

       partSize = ceil(n / procs);

       MPI_Scatter(x, partSize, MPI_DOUBLE, local_x, partSize, MPI_DOUBLE, 0, MPI_COMM_WORLD);

       MPI_Scatter(y, partSize, MPI_DOUBLE, local_y, partSize, MPI_DOUBLE, 0, MPI_COMM_WORLD);

 

       /* Partial Inner Product */

       local_prod = 0;

       for (i=0; i<partSize; i++) {

              local_prod += local_x[i] * local_y[i];

       }

 

       MPI_Reduce(&local_prod, &prod, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD);

 

       if (rank==0) {

              printf("Computed Inner Product\t=\t%.6f\n", prod);

              printf("True Inner Product\t=\t%.6f\n", trueProd);

              fflush(stdout);

       }

 

       MPI_Finalize();

 

       return(0);

}