source: CIVL/examples/mpi-pthread/mpi-pthreads-marix-vector.c@ 2dfc427

1.23 2.0 main test-branch
Last change on this file since 2dfc427 was cf6908a, checked in by Manchun Zheng <zmanchun@…>, 11 years ago

fixed mpi-pthreads matrix multiplication program.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@2007 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 7.7 KB
Line 
1
2/********************************************************************
3
4 C-DAC Tech Workshop : hyPACK-2013
5 Oct 15-18,2013
6
7 Example 1.4 : mpi-Pthreads-matrix-vector.c
8
9 Objective : To write an MPI-Pthreads program, for computing
10 the matrix-vector multiplication using
11 Self-Scheduling algorithm. Pthreads and MPI library
12 calls are used.
13
14 This example demonstrates use of:
15
16 pthread_create()
17 pthread_join()
18 pthread_mutex_lock()
19 pthread_mutex_unlock()
20
21 MPI_Init
22 MPI_Comm_rank
23 MPI_Comm_size
24 MPI_Barrier
25 MPI_Bcast
26 MPI_Allgather
27 MPI_Gatherv
28 MPI_Finalize
29
30 Input : Number of Rows, Columns of the Matrix
31
32 Output : Product of Matrix Vector Multiplication.
33
34 Created :MAY-2013
35
36 E-mail : hpcfte@cdac.in
37
38
39 **************************************************************************/
40#include<stdlib.h>
41#include <pthread.h>
42#include "mpi.h"
43#include <stdio.h>
44
45#ifdef _CIVL
46$input int NUM_ROWS_BOUND = 6;
47$input int NUM_COLS_BOUND = 6;
48#endif
49
50int MyRank, currentRow, MyNoofRows, NoofCols, GlobalIndex = -1;
51float **Matrix, *Vector, *MyResult;
52int flag = 0, rowlimit;
53
54pthread_mutex_t mutex_Row = PTHREAD_MUTEX_INITIALIZER;
55pthread_mutex_t mutex_Flag = PTHREAD_MUTEX_INITIALIZER;
56
57/* Routine executed by each thread */
58
59void * MyPartOfCalc(int Id)
60{
61 int myRow, icol, myindex;
62
63 if (flag == 0)
64 {
65 pthread_mutex_lock(&mutex_Flag);
66 rowlimit = currentRow + MyNoofRows;
67 flag++;
68 pthread_mutex_unlock(&mutex_Flag);
69 }
70 while (1)
71 {
72
73 /*
74 * Thread selects the row of Matrix on which it has to do the
75 * operation
76 */
77
78 pthread_mutex_lock(&mutex_Row);
79 {
80 if (currentRow >= rowlimit)
81 {
82 pthread_mutex_unlock(&mutex_Row);
83 pthread_exit(0);
84 }
85 myRow = currentRow;
86 currentRow++;
87 GlobalIndex++;
88 myindex = GlobalIndex;
89 }
90 pthread_mutex_unlock(&mutex_Row);
91
92 /*
93 * Perform the multiplication on the row selected and store
94 * the addendum in MyResult array
95 */
96
97 printf(" Thread Id %d of process with Rank %d operated on Matrix Row %d\n", Id, MyRank, myRow);
98 MyResult[myindex] = 0.0;
99
100 for (icol = 0; icol < NoofCols; icol++)
101 MyResult[myindex] += Matrix[myRow][icol] * Vector[icol];
102 }
103
104}
105
106
107int main(int argc, char **argv)
108{
109
110 int iproc, irow, icol, modval, divval, *Displacement, iprocb, *ArrayNoofRows;
111 int Numprocs, Root = 0, NoofRows, VectorSize;
112 float *Results;
113
114 pthread_t *threads;
115
116
117 /* MPI Initialisation ... */
118
119 MPI_Init(&argc, &argv);
120 MPI_Comm_rank(MPI_COMM_WORLD, &MyRank);
121 MPI_Comm_size(MPI_COMM_WORLD, &Numprocs);
122
123 /* Validity checking for minimum number of processors */
124
125 if (Numprocs < 2)
126 {
127 printf("Invalid Number of Processors ..... \n");
128 printf("Numprocs must be greater than 1 ......\n");
129 MPI_Finalize();
130 exit(0);
131 }
132 /* Read the sizes of Matrix and Vector */
133
134 if (MyRank == Root)
135 {
136 printf("Enter the number of rows and columns of Matrix\n");
137 scanf("%d %d", &NoofRows, &NoofCols);
138 printf("Enter the size of Vector\n");
139 scanf("%d", &VectorSize);
140 #ifdef _CIVL
141 $assume NoofRows <= NUM_ROWS_BOUND;
142 $assume NoofCols <= NUM_COLS_BOUND;
143 #endif
144 }
145 MPI_Barrier(MPI_COMM_WORLD);
146
147 MPI_Bcast(&NoofRows, 1, MPI_INT, Root, MPI_COMM_WORLD);
148 MPI_Bcast(&NoofCols, 1, MPI_INT, Root, MPI_COMM_WORLD);
149 MPI_Bcast(&VectorSize, 1, MPI_INT, Root, MPI_COMM_WORLD);
150
151 /* Validity checking for negative sizes of Matrix and Vector */
152
153 #ifdef _CIVL
154 $assume NoofRows >= 1 && NoofCols >= 1 && VectorSize >= 1;
155 #endif
156 if (NoofRows < 1 || NoofCols < 1 || VectorSize < 1)
157 {
158 printf("The number of rows,columns or size of Vector should be atleast one\n");
159 MPI_Finalize();
160 exit(-1);
161 }
162 /* Validity checking for minimum number of Rows of Matrix */
163
164 #ifdef _CIVL
165 $assume NoofRows >= Numprocs;
166 #endif
167 if (NoofRows < Numprocs)
168 {
169 printf("The number of rows of Matrix should be greater than number of processors\n");
170 MPI_Finalize();
171 exit(-1);
172 }
173 /* Validity checking for suitability of sizes for multiplication */
174 #ifdef _CIVL
175 $assume NoofCols == VectorSize;
176 #endif
177 if (NoofCols != VectorSize)
178 {
179 printf("The number of columns of Matrix should be equal to size of Vector\n");
180 MPI_Finalize();
181 exit(-1);
182 }
183 /* Allocating and Populating the Matrices */
184
185 Matrix = (float **) malloc(NoofRows * sizeof(float *));
186 for (irow = 0; irow < NoofRows; irow++)
187 Matrix[irow] = (float *) malloc(NoofCols * sizeof(float));
188
189 //Vector = (float *) malloc(NoofRows * sizeof(float));
190 Vector = (float *) malloc(NoofCols * sizeof(float));
191
192 for (icol = 0; icol < NoofCols; icol++)
193 {
194 for (irow = 0; irow < NoofRows; irow++)
195 Matrix[irow][icol] = irow + icol;
196 Vector[icol] = icol;
197 }
198
199
200 /* Storing the number of Rows to be operated by each process in array */
201
202 modval = NoofRows % Numprocs;
203 divval = NoofRows / Numprocs;
204 MyNoofRows = (MyRank < modval ? divval + 1 : divval);
205
206 ArrayNoofRows = (int *) malloc(Numprocs * sizeof(int));
207 MPI_Allgather(&MyNoofRows, 1, MPI_INT, ArrayNoofRows, 1, MPI_INT, MPI_COMM_WORLD);
208
209 /* Storing the starting Row to be operated by each process in array */
210
211 Displacement = (int *) malloc(Numprocs * sizeof(int));
212 Displacement[0] = 0;
213
214
215 for (iproc = 1; iproc < Numprocs; iproc++)
216 Displacement[iproc] = Displacement[iproc - 1] + ArrayNoofRows[iproc - 1];
217
218 MyResult = (float *) malloc(MyNoofRows * sizeof(float));
219
220 currentRow = Displacement[MyRank];
221
222 MPI_Barrier(MPI_COMM_WORLD);
223
224 /*
225 * Call threads equal to number of Rows to be processed by this
226 * process
227 */
228
229 threads = (pthread_t *) malloc(sizeof(pthread_t) * MyNoofRows);
230
231 for (irow = 0; irow < MyNoofRows; irow++)
232 pthread_create(&threads[irow], NULL, (void *(*) (void *)) MyPartOfCalc, (void *) irow);
233
234 MPI_Barrier(MPI_COMM_WORLD);
235 for (irow = 0; irow < MyNoofRows; irow++)
236 pthread_join(threads[irow], NULL);
237
238 MPI_Barrier(MPI_COMM_WORLD);
239
240 /* Collection of results from each process using MPI_Gatherv */
241
242 Results = (float *) malloc(NoofRows * sizeof(float));
243
244
245 MPI_Gatherv(MyResult, MyNoofRows, MPI_FLOAT, Results, ArrayNoofRows, Displacement, MPI_FLOAT, Root, MPI_COMM_WORLD);
246
247 /* Printing of the Matrix , Vector and the Result Vector by Root */
248
249 if (MyRank == Root)
250 {
251 printf("\n\nMatrix is\n\n");
252 for (irow = 0; irow < NoofRows; irow++)
253 {
254 printf("Row %d : ", irow);
255 for (icol = 0; icol < NoofCols; icol++)
256 printf(" %f ", Matrix[irow][icol]);
257 printf("\n");
258 }
259 printf("\n");
260 printf("\n");
261
262 printf("Vector is\n\n");
263 for (icol = 0; icol < NoofCols; icol++)
264 printf("Row %d : %f \n", icol, Vector[icol]);
265
266 printf("\n");
267 printf("\n");
268
269 printf("\n\nResult Vector is \n\n");
270 for (irow = 0; irow < NoofRows; irow++)
271 printf("Row %d : %f \n", irow, Results[irow]);
272 }
273 printf("\n");
274 for (irow = 0; irow < NoofRows; irow++)
275 free(Matrix[irow]);
276 free(Matrix);
277 free(Vector);
278 free(ArrayNoofRows);
279 free(Displacement);
280 free(MyResult);
281 free(threads);
282 free(Results);
283 MPI_Finalize();
284 return 0;
285}
Note: See TracBrowser for help on using the repository browser.