001 /*
002 * $Id: MatrixMultMPI.java,v 1.5 2002/08/03 17:17:42 kredel Exp $
003 */
004 //package edu.unima.ky.parallel.mpijava;
005
006 import mpi.* ;
007
008 /**
009 * Matrix Multiplication.
010 * sequential and parallel using MPI.
011 * @author Akitoshi Yoshida
012 * @author Heinz Kredel.
013 */
014 public class MatrixMultMPI {
015
016 /**
017 * @param C two-dimensional double array.
018 * @param A two-dimensional double array.
019 * @param B two-dimensional double array.
020 */
021 public void seqmult(double[][] C, double[][] A, double[][] B) {
022 for (int i=0; i < A.length; i++) {
023 for (int j=0; j < B[0].length; j++) {
024 double c = 0.0;
025 for (int k=0; k < B.length; k++) {
026 c += A[i][k] * B[k][j];
027 }
028 C[i][j] = c;
029 }
030 }
031 }
032
033 /**
034 * @param C two-dimensional double array.
035 * @param A two-dimensional double array.
036 * @param B two-dimensional double array.
037 * @throws MPIException.
038 */
039 public void parmult(double[][] C, double[][] A, double[][] B)
040 throws MPIException {
041
042 boolean prnt = false;
043
044 // initialize MPI Communicators
045 int myid = MPI.COMM_WORLD.Rank() ;
046 int numprocs = MPI.COMM_WORLD.Size() ;
047 if (prnt) {
048 System.out.println("ExVecMPI on " + myid
049 + " of " + numprocs + " ") ;
050 }
051 int counts = A.length;
052 int[] assign = new int[counts];
053 for (int k=0; k < counts; k++) {
054 assign[k] = k % numprocs;
055 }
056
057 /* transfer data */
058 int msgtag = 4711;
059 if ( myid == 0 ) {
060 if (prnt) {
061 System.out.print("assign = ");
062 vecprint(assign);
063 System.out.print("sending A ");
064 }
065 for (int k=0; k < counts; k++ ) {
066 if ( myid != assign[k] ) {
067 MPI.COMM_WORLD.Send(A[k], 0, A[k].length, MPI.DOUBLE, assign[k], msgtag);
068 }
069 }
070 } else {
071 for (int y = 0; y < counts; y++ ) {
072 if ( myid == assign[y] ) {
073 MPI.COMM_WORLD.Recv(A[y], 0, A[y].length, MPI.DOUBLE, 0, msgtag);
074 }
075 }
076 }
077 if ( myid == 0 ) {
078 if (prnt) {
079 System.out.print("sending B ");
080 }
081 }
082 for (int x=0; x < B.length; x++ ){
083 MPI.COMM_WORLD.Bcast(B[x], 0, B[x].length, MPI.DOUBLE, 0);
084 }
085
086 for (int i=0; i < counts; i++) {
087 if ( myid == assign[i] ) {
088 for (int j=0; j < B[0].length; j++) {
089 double c = 0.0;
090 for (int k=0; k < B.length; k++) {
091 c += A[i][k] * B[k][j];
092 }
093 C[i][j] = c;
094 }
095 }
096 }
097
098 if ( myid == 0 ) {
099 if (prnt) {
100 System.out.print("receiving C ");
101 }
102 for (int k=0; k < counts; k++ ) {
103 if ( myid != assign[k] ) {
104 MPI.COMM_WORLD.Recv(C[k], 0, C[k].length, MPI.DOUBLE, assign[k], msgtag);
105 }
106 }
107 } else {
108 for (int y = 0; y < counts; y++ ) {
109 if ( myid == assign[y] ) {
110 MPI.COMM_WORLD.Send(C[y], 0, C[y].length, MPI.DOUBLE, 0, msgtag);
111 }
112 }
113 }
114
115
116 }
117
118 /**
119 * @param C two-dimensional double array.
120 * @param A two-dimensional double array.
121 * @param B two-dimensional double array.
122 */
123 public void seqdiff(double[][] C, double[][] A, double[][] B) {
124 for (int i=0; i < C.length; i++) {
125 for (int j=0; j < C[0].length; j++) {
126 C[i][j] = A[i][j] - B[i][j];
127 }
128 }
129 }
130
131 /**
132 * @param C two-dimensional double array.
133 * @param A two-dimensional double array.
134 * @param B two-dimensional double array.
135 * @param i row of A.
136 * @param j column of B.
137 */
138 public void dotmult(double[][] C, double[][] A, double[][] B, int i, int j) {
139 double c = 0.0;
140 for (int k=0; k < B.length; k++) {
141 c += A[i][k] * B[k][j];
142 }
143 C[i][j] = c;
144 }
145
146 /**
147 * @param C two-dimensional double array.
148 * @param A two-dimensional double array.
149 * @param B two-dimensional double array.
150 */
151 public void seq2mult(double[][] C, double[][] A, double[][] B) {
152 for (int i=0; i < A.length; i++) {
153 for (int j=0; j < B[0].length; j++) {
154 dotmult(C,A,B,i,j);
155 }
156 }
157 }
158
159 /**
160 * @param n rows of result.
161 * @param m columns of result.
162 * @return A.
163 */
164 public double[][] matgen(int n, int m) {
165 double[][] A = new double[n][m];
166 for (int i=0; i < n; i++) {
167 for (int j=0; j < m; j++) {
168 A[i][j] = Math.random();
169 }
170 }
171 return A;
172 }
173
174 /**
175 * @param n rows of result.
176 * @param m columns of result.
177 * @return A.
178 */
179 public double[][] matgen0(int n, int m) {
180 double[][] A = new double[n][m];
181 for (int i=0; i < n; i++) {
182 for (int j=0; j < m; j++) {
183 A[i][j] = 0.0;
184 }
185 }
186 return A;
187 }
188 /**
189 * @param n rows of result.
190 * @param m columns of result.
191 * @return A.
192 */
193 public double[][] matgen1(int n, int m) {
194 double[][] A = new double[n][m];
195 for (int i=0; i < n; i++) {
196 for (int j=0; j < m; j++) {
197 if (i == j) A[i][j] = 1.0; else A[i][j]= 0.0;
198 }
199 }
200 return A;
201 }
202
203 /**
204 * @param A two-dimensional double array.
205 */
206 public void matprint(double[][] A) {
207 for (int i=0; i < A.length; i++) {
208 for (int j=0; j < A[0].length; j++) {
209 System.out.print(A[i][j] + " ");
210 }
211 System.out.println();
212 }
213 }
214
215 /**
216 * @param V vector.
217 */
218 public void vecprint(int[] V) {
219 for (int i=0; i < V.length; i++) {
220 System.out.print(V[i] + " ");
221 }
222 System.out.println();
223 }
224
225 /**
226 * @param A two-dimensional double array.
227 * @return true if A is approximately zero.
228 */
229 public boolean matcheck0(double[][] A) {
230 double eps = Double.MIN_VALUE*1000.0;
231 for (int i=0; i < A.length; i++) {
232 for (int j=0; j < A[0].length; j++) {
233 if ( Math.abs(A[i][j]) > eps) return false;
234 }
235 }
236 return true;
237 }
238
239 public static void main(String[] args) throws MPIException {
240
241 int n = 300, m = 300;
242 boolean prnt = false;
243
244 try { n = Integer.parseInt(args[0]); }
245 catch (Exception e) { }
246 try { m = Integer.parseInt(args[1]); }
247 catch (Exception e) { }
248 try { prnt = Boolean.valueOf(args[2]).booleanValue(); }
249 catch (Exception e) { }
250
251 //prnt=true;
252
253 MPI.Init(args) ;
254 int myid = MPI.COMM_WORLD.Rank() ;
255
256 MatrixMultMPI x = new MatrixMultMPI();
257
258 double[][] A;
259 double[][] B;
260 double[][] C;
261 double[][] D;
262 long tm =0;
263
264 if ( myid == 0 ) {
265 A = x.matgen1(n,m);
266 B = x.matgen(m,n);
267 C = x.matgen0(n,n);
268 D = x.matgen0(n,n);
269 } else {
270 A = new double[n][m];
271 B = new double[m][n];
272 C = new double[n][n];
273 D = new double[n][n];
274 }
275
276 if ( myid == 0 ) {
277 System.out.println("A = ");
278 if (prnt) x.matprint(A);
279 System.out.println("");
280
281 System.out.println("B = ");
282 if (prnt) x.matprint(B);
283 System.out.println("");
284
285 System.out.println("C = ");
286 tm = System.currentTimeMillis();
287 x.seqmult(C,A,B);
288 tm = System.currentTimeMillis() - tm;
289 System.out.println(tm + "ms");
290 }
291
292 tm = System.currentTimeMillis();
293 x.parmult(C,A,B);
294 tm = System.currentTimeMillis() - tm;
295
296 if ( myid == 0 ) {
297 System.out.println(tm + "ms");
298 if (prnt) x.matprint(C);
299 System.out.println("");
300
301 System.out.println("D = ");
302 x.seqdiff(D,B,C);
303 if (prnt) x.matprint(D);
304 System.out.println("");
305 System.out.println("D is zero = " + x.matcheck0(D) );
306 }
307
308 MPI.Finalize();
309
310 }
311
312 }