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    }