001    /*
002     * $Id: MatrixMultOmp.jomp,v 1.5 2002/08/03 17:14:31 kredel Exp $
003     */
004    
005    //package edu.unima.ky.parallel.jomp;
006    
007    /**
008     * Matrix Multiplication 
009     * sequential and parallel using OpenMP
010     * @author Akitoshi Yoshida
011     * @author Heinz Kredel.
012     */
013    
014    public class MatrixMultOmp {
015    
016    
017    /**
018     * @param C two-dimensional double array.
019     * @param A two-dimensional double array.
020     * @param B two-dimensional double array.
021     */
022      public void seqmult(double[][] C, double[][] A, double[][] B) {
023          for (int i=0; i < A.length; i++) {
024              for (int j=0; j < B[0].length; j++) {
025                  double c = 0.0;
026                  for (int k=0; k < B.length; k++) {
027                      c += A[i][k] * B[k][j];
028                  }
029                  C[i][j] = c;
030              }
031          }
032      }
033    
034    
035    /**
036     * @param C two-dimensional double array.
037     * @param A two-dimensional double array.
038     * @param B two-dimensional double array.
039     */
040      public void parmult(double[][] C, double[][] A, double[][] B) {
041    
042    // OMP PARALLEL BLOCK BEGINS
043    {
044      __omp_Class0 __omp_Object0 = new __omp_Class0();
045      // shared variables
046      __omp_Object0.B = B;
047      __omp_Object0.A = A;
048      __omp_Object0.C = C;
049      // firstprivate variables
050      try {
051        jomp.runtime.OMP.doParallel(__omp_Object0);
052      } catch(Throwable __omp_exception) {
053        System.err.println("OMP Warning: Illegal thread exception ignored!");
054        System.err.println(__omp_exception);
055      }
056      // reduction variables
057      // shared variables
058      B = __omp_Object0.B;
059      A = __omp_Object0.A;
060      C = __omp_Object0.C;
061    }
062    // OMP PARALLEL BLOCK ENDS
063    
064      }
065    
066    
067    /**
068     * @param C two-dimensional double array.
069     * @param A two-dimensional double array.
070     * @param B two-dimensional double array.
071     */
072      public void seqdiff(double[][] C, double[][] A, double[][] B) {
073          for (int i=0; i < C.length; i++) {
074              for (int j=0; j < C[0].length; j++) {
075                  C[i][j] = A[i][j] - B[i][j];
076              }
077          }
078      }
079    
080    
081    /**
082     * @param C two-dimensional double array.
083     * @param A two-dimensional double array.
084     * @param B two-dimensional double array.
085     * @param i row of A.
086     * @param j column of B.
087     */
088      public void dotmult(double[][] C, double[][] A, double[][] B, int i, int 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     * @param C two-dimensional double array.
099     * @param A two-dimensional double array.
100     * @param B two-dimensional double array.
101     */
102      public void seq2mult(double[][] C, double[][] A, double[][] B) {
103          for (int i=0; i < A.length; i++) {
104              for (int j=0; j < B[0].length; j++) {
105                  dotmult(C,A,B,i,j);
106              }
107          }
108      }
109    
110    
111    /**
112     * @param n rows of result.
113     * @param m columns of result.
114     * @return A two-dimensional double array.
115     */
116      public double[][] matgen(int n, int m) {
117          double A[][] = new double[n][m];
118          for (int i=0; i < n; i++) {
119              for (int j=0; j < m; j++) {
120                  A[i][j] = Math.random();
121              }
122          }
123          return A;
124      }
125    
126    
127    /**
128     * @param n rows of result.
129     * @param m columns of result.
130     * @return A two-dimensional double array.
131     */
132      public double[][] matgen0(int n, int m) {
133          double A[][] = new double[n][m];
134          for (int i=0; i < n; i++) {
135              for (int j=0; j < m; j++) {
136                  A[i][j] = 0.0;
137              }
138          }
139          return A;
140      }
141    
142    
143    /**
144     * @param n rows of result.
145     * @param m columns of result.
146     * @return A two-dimensional double array.
147     */
148      public double[][] matgen1(int n, int m) {
149          double A[][] = new double[n][m];
150          for (int i=0; i < n; i++) {
151              for (int j=0; j < m; j++) {
152                  if (i == j) A[i][j] = 1.0; else A[i][j]= 0.0;
153              }
154          }
155          return A;
156      }
157       
158    
159    /**
160     * @param A two-dimensional double array. 
161     */
162      public void matprint(double[][] A) {
163          for (int i=0; i < A.length; i++) {
164              for (int j=0; j < A[0].length; j++) {
165                  System.out.print(A[i][j] + " ");
166              }
167              System.out.println();
168          }
169      }
170    
171    
172    /**
173     * @param A two-dimensional double array.
174     * @return true if A is approximately zero.
175     */
176      public boolean matcheck0(double[][] A) {
177          double eps = Double.MIN_VALUE*1000.0;
178          for (int i=0; i < A.length; i++) {
179              for (int j=0; j < A[0].length; j++) {
180                  if ( Math.abs(A[i][j]) > eps) return false;
181              }
182          }
183          return true;
184      }
185    
186    
187    /**
188     */
189      public static void main(String[] args) {
190    
191            int n = 200, m = 400;
192            boolean prnt = false;
193    
194            try { n = Integer.parseInt(args[0]); }
195            catch (Exception e) { }
196            try { m = Integer.parseInt(args[1]); }
197            catch (Exception e) { }
198            try { prnt = Boolean.valueOf(args[2]).booleanValue(); }
199            catch (Exception e) { }
200    
201            MatrixMultOmp x = new MatrixMultOmp();
202    
203            double[][] A = x.matgen1(n,m);
204            double[][] B = x.matgen(m,n);
205            double[][] C = x.matgen0(n,n);
206            double[][] D = x.matgen0(n,n);
207     
208            System.out.println("A = ");
209            if (prnt) x.matprint(A);
210            System.out.println("");
211    
212            System.out.println("B = ");
213            if (prnt) x.matprint(B);
214            System.out.println("");
215    
216            System.out.println("C = ");
217            long tm = System.currentTimeMillis();
218            x.seqmult(C,A,B);
219            tm = System.currentTimeMillis() - tm; 
220            System.out.println(tm + "ms");
221            //x.seq2mult(C,A,B);
222            tm = System.currentTimeMillis();
223            x.parmult(C,A,B);
224            tm = System.currentTimeMillis() - tm; 
225            System.out.println(tm + "ms");
226            if (prnt) x.matprint(C);
227            System.out.println("");
228    
229            System.out.println("D = ");
230            x.seqdiff(D,B,C);
231            if (prnt) x.matprint(D);
232            System.out.println("");
233            System.out.println("D is zero = " + x.matcheck0(D) );
234    
235        }
236    
237    // OMP PARALLEL REGION INNER CLASS DEFINITION BEGINS
238    private class __omp_Class0 extends jomp.runtime.BusyTask {
239      // shared variables
240      double [ ] [ ] B;
241      double [ ] [ ] A;
242      double [ ] [ ] C;
243      // firstprivate variables
244      // variables to hold results of reduction
245    
246      public void go(int __omp_me) throws Throwable {
247      // firstprivate variables + init
248      // private variables
249      // reduction variables, init to default
250        // OMP USER CODE BEGINS
251    
252              { // OMP FOR BLOCK BEGINS
253              // copy of firstprivate variables, initialized
254              // copy of lastprivate variables
255              // variables to hold result of reduction
256              boolean amLast=false;
257              {
258                // firstprivate variables + init
259                // [last]private variables
260                // reduction variables + init to default
261                // -------------------------------------
262                jomp.runtime.LoopData __omp_WholeData2 = new jomp.runtime.LoopData();
263                jomp.runtime.LoopData __omp_ChunkData1 = new jomp.runtime.LoopData();
264                __omp_WholeData2.start = (long)(0);
265                __omp_WholeData2.stop = (long)( A.length);
266                __omp_WholeData2.step = (long)(1);
267                jomp.runtime.OMP.setChunkStatic(__omp_WholeData2);
268                while(!__omp_ChunkData1.isLast && jomp.runtime.OMP.getLoopStatic(__omp_me, __omp_WholeData2, __omp_ChunkData1)) {
269                for(;;) {
270                  if(__omp_WholeData2.step > 0) {
271                     if(__omp_ChunkData1.stop > __omp_WholeData2.stop) __omp_ChunkData1.stop = __omp_WholeData2.stop;
272                     if(__omp_ChunkData1.start >= __omp_WholeData2.stop) break;
273                  } else {
274                     if(__omp_ChunkData1.stop < __omp_WholeData2.stop) __omp_ChunkData1.stop = __omp_WholeData2.stop;
275                     if(__omp_ChunkData1.start > __omp_WholeData2.stop) break;
276                  }
277                  for(int i = (int)__omp_ChunkData1.start; i < __omp_ChunkData1.stop; i += __omp_ChunkData1.step) {
278                    // OMP USER CODE BEGINS
279     {
280              for (int j=0; j < B[0].length; j++) {
281                  double c = 0.0;
282                  for (int k=0; k < B.length; k++) {
283                      c += A[i][k] * B[k][j];
284                  }
285                  C[i][j] = c;
286              }
287          }
288                    // OMP USER CODE ENDS
289                    if (i == (__omp_WholeData2.stop-1)) amLast = true;
290                  } // of for 
291                  if(__omp_ChunkData1.startStep == 0)
292                    break;
293                  __omp_ChunkData1.start += __omp_ChunkData1.startStep;
294                  __omp_ChunkData1.stop += __omp_ChunkData1.startStep;
295                } // of for(;;)
296                } // of while
297                // call reducer
298                jomp.runtime.OMP.doBarrier(__omp_me);
299                // copy lastprivate variables out
300                if (amLast) {
301                }
302              }
303              // set global from lastprivate variables
304              if (amLast) {
305              }
306              // set global from reduction variables
307              if (jomp.runtime.OMP.getThreadNum(__omp_me) == 0) {
308              }
309              } // OMP FOR BLOCK ENDS
310    
311        // OMP USER CODE ENDS
312      // call reducer
313      // output to _rd_ copy
314      if (jomp.runtime.OMP.getThreadNum(__omp_me) == 0) {
315      }
316      }
317    }
318    // OMP PARALLEL REGION INNER CLASS DEFINITION ENDS
319    
320    }
321