|
| 1 | +#include <mpi.h> |
| 2 | +#include <stdio.h> |
| 3 | +#include <stdlib.h> |
| 4 | +#include <string.h> |
| 5 | +#include <math.h> |
| 6 | +#include <time.h> |
| 7 | + |
| 8 | +float tolerance = 0.000001; |
| 9 | + |
| 10 | +float my_random(){ |
| 11 | + float val = (double)rand()/(double)RAND_MAX; |
| 12 | + return val; |
| 13 | +} |
| 14 | + |
| 15 | +void read_data(float* arr,char str[],int rows,int cols){ |
| 16 | + FILE *file_pointer; |
| 17 | + file_pointer = fopen(str,"r"); |
| 18 | + for(int i = 0;i<rows;i++){ |
| 19 | + for(int j = 0;j<cols;j++){ |
| 20 | + fscanf(file_pointer,"%f ",&arr[i*cols + j]); |
| 21 | + } |
| 22 | + } |
| 23 | + |
| 24 | + fclose(file_pointer); |
| 25 | +} |
| 26 | + |
| 27 | +void write_data(char file_name[],float* matrix,int rows,int cols){ |
| 28 | + FILE *file_pointer; |
| 29 | + file_pointer = fopen(file_name,"w"); |
| 30 | + for(int i = 0;i<rows;i++){ |
| 31 | + for(int j = 0;j<cols;j++){ |
| 32 | + fprintf(file_pointer, "%f",matrix[i*cols + j]); |
| 33 | + if(j!=cols-1){ |
| 34 | + fprintf(file_pointer, " "); |
| 35 | + }else if(i!=rows-1){ |
| 36 | + fprintf(file_pointer, "\n"); |
| 37 | + } |
| 38 | + } |
| 39 | + } |
| 40 | + fclose(file_pointer); |
| 41 | + return; |
| 42 | +} |
| 43 | + |
| 44 | +void generate_data(float* arr,int rows,int cols){ |
| 45 | + for(int i = 0;i<rows;i++){ |
| 46 | + for(int j = 0;j<cols;j++){ |
| 47 | + arr[i*cols + j] = my_random(); |
| 48 | + } |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +void print(float* array,int rows,int cols){ |
| 53 | + for(int i = 0;i<rows;i++){ |
| 54 | + for(int j = 0;j<cols;j++){ |
| 55 | + printf("%f ",array[i*cols + j]); |
| 56 | + } |
| 57 | + printf("\n"); |
| 58 | + } |
| 59 | + printf("**********THE END**********\n"); |
| 60 | +} |
| 61 | + |
| 62 | +void transpose(float* array,float* arrayT,int rows,int cols){ |
| 63 | + for(int i = 0;i<cols;i++){ |
| 64 | + for(int j = 0;j<rows;j++){ |
| 65 | + arrayT[i*rows+j] = array[j*cols + i]; |
| 66 | + } |
| 67 | + } |
| 68 | +} |
| 69 | + |
| 70 | +void multiply(float* A,float* B,float* prod,int n,int m){ |
| 71 | + int i,j,k; |
| 72 | + float val = 0; |
| 73 | + |
| 74 | + for(i = 0;i<n;i++){ |
| 75 | + for(j = 0;j<n;j++){ |
| 76 | + val = 0; |
| 77 | + for(k = 0;k<m;k++){ |
| 78 | + val+=(A[i*m + k] * B[k*n + j]); |
| 79 | + } |
| 80 | + prod[i*n + j] = val; |
| 81 | + } |
| 82 | + } |
| 83 | +} |
| 84 | + |
| 85 | +void IsEqual(float* A,float* B,int n){ |
| 86 | + for(int i = 0;i<n;i++){ |
| 87 | + if(fabs(A[i] - B[i])>tolerance){ |
| 88 | + printf("Incorrect\n"); |
| 89 | + return; |
| 90 | + } |
| 91 | + } |
| 92 | + printf("Correct\n"); |
| 93 | +} |
| 94 | + |
| 95 | +int main(int argc, char* argv[]){ |
| 96 | + int n = atoi(argv[1]); |
| 97 | + int m = 32; |
| 98 | + char* file_name1 = argv[2]; |
| 99 | + char* file_name2 = argv[3]; |
| 100 | + int num_workers = atoi(argv[4]); |
| 101 | + |
| 102 | + float A[n][m]; |
| 103 | + float B[n][m]; |
| 104 | + float C[m][n]; |
| 105 | + float prodM[n][n]; |
| 106 | + float prodS[n][n]; |
| 107 | + |
| 108 | + |
| 109 | + // Initialize the MPI Environment |
| 110 | + MPI_Init(&argc,&argv); |
| 111 | + clock_t t; |
| 112 | + int rank,idx; |
| 113 | + MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
| 114 | + |
| 115 | + int load,extra,num_rows,num_cols; |
| 116 | + |
| 117 | + if(rank==0){ |
| 118 | + // read_data(A,file_name1,n,m); |
| 119 | + // read_data(C,file_name2,m,n); |
| 120 | + |
| 121 | + generate_data(A,n,32); |
| 122 | + generate_data(C,32,n); |
| 123 | + transpose(C,B,m,n); |
| 124 | + |
| 125 | + idx = 0; |
| 126 | + num_workers-=1; |
| 127 | + load = n/num_workers; |
| 128 | + t = clock(); |
| 129 | + |
| 130 | + for(int i = 1;i<=num_workers;i++){ |
| 131 | + if(i==num_workers && num_workers>1){ |
| 132 | + load = n%num_workers; |
| 133 | + } |
| 134 | + MPI_Send(&n,1,MPI_INT,i,0,MPI_COMM_WORLD); |
| 135 | + MPI_Send(&m,1,MPI_INT,i,0,MPI_COMM_WORLD); |
| 136 | + MPI_Send(&load,1,MPI_INT,i,0,MPI_COMM_WORLD); |
| 137 | + MPI_Send(&A[idx][0],load*m,MPI_FLOAT,i,0,MPI_COMM_WORLD); |
| 138 | + MPI_Send(&B[0][0],n*m,MPI_FLOAT,i,0,MPI_COMM_WORLD); |
| 139 | + idx+=load; |
| 140 | + } |
| 141 | + |
| 142 | + idx = 0; |
| 143 | + load = n/num_workers; |
| 144 | + for(int i = 1;i<=num_workers;i++){ |
| 145 | + if(i==num_workers && num_workers>1){ |
| 146 | + load = n%num_workers; |
| 147 | + } |
| 148 | + MPI_Recv(&prodM[idx][0],load*n,MPI_FLOAT,i,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 149 | + idx+=load; |
| 150 | + } |
| 151 | + |
| 152 | + t = clock()-t; |
| 153 | + double time_taken = ((double)t)/CLOCKS_PER_SEC; |
| 154 | + printf("Time taken:- %lf\n",time_taken); |
| 155 | + |
| 156 | + multiply(A,C,prodS,n,m); |
| 157 | + |
| 158 | + print(prodM,n,n); |
| 159 | + print(prodS,n,n); |
| 160 | + IsEqual(prodS,prodM,n*n); |
| 161 | + |
| 162 | + char file_name[30] = "product_P2PB_"; |
| 163 | + sprintf(file_name+13,"%d",n); |
| 164 | + strcat(file_name,".txt"); |
| 165 | + write_data(file_name,prodM,n,n); |
| 166 | + |
| 167 | + }else{ |
| 168 | + MPI_Recv(&num_rows,1,MPI_INT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 169 | + MPI_Recv(&num_cols,1,MPI_INT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 170 | + MPI_Recv(&load,1,MPI_INT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 171 | + MPI_Recv(&A[0][0],load*num_cols,MPI_FLOAT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 172 | + MPI_Recv(&B[0][0],num_rows*num_cols,MPI_FLOAT,0,0,MPI_COMM_WORLD,MPI_STATUS_IGNORE); |
| 173 | + |
| 174 | + double val; |
| 175 | + for(int i = 0;i<load;i++){ |
| 176 | + for(int j = 0;j<num_rows;j++){ |
| 177 | + val = 0; |
| 178 | + for(int k = 0;k<num_cols;k++){ |
| 179 | + val+=(A[i][k]*B[j][k]); |
| 180 | + } |
| 181 | + C[i][j] = val; |
| 182 | + } |
| 183 | + } |
| 184 | + |
| 185 | + MPI_Send(&C[0][0],load*num_rows,MPI_FLOAT,0,0,MPI_COMM_WORLD); |
| 186 | + } |
| 187 | + |
| 188 | + MPI_Finalize(); |
| 189 | + return 0; |
| 190 | +} |
0 commit comments