source: CIVL/examples/omp/simple/matProduct2.c.s@ beab7f2

main test-branch
Last change on this file since beab7f2 was ea777aa, checked in by Alex Wilton <awilton@…>, 3 years ago

Moved examples, include, build_default.properties, common.xml, and README out from dev.civl.com into the root of the repo.

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

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*
2 OpenMP implementation of matrix multiplication. Each thread takes care
3 a chunk of rows.
4
5 Compile with gcc -O3 -fopenmp omp_matrixmult.c -o omp_matrixmult
6*/
7// Online source: http://users.abo.fi/mats/PP2012/examples/OpenMP/omp_critical.c
8// permission obtained
9
10#include <omp.h>
11#include <stdio.h>
12#include <stdlib.h>
13
14/* Number of threads used */
15#define NR_THREADS 4
16
17/*
18#define DEBUG 0
19
20#define NRA 1400 // number of rows in matrix A
21#define NCA 1400 // number of columns in matrix A
22#define NCB 1400 // number of columns in matrix B
23*/
24
25/* Use smaller matrices for testing and debugging */
26#define DEBUG 1
27#define NRA 10 // number of rows in matrix A
28#define NCA 10 // number of columns in matrix A
29#define NCB 10 // number of columns in matrix B
30
31
32int main (int argc, char *argv[]) {
33 int tid, nthreads, i, j, k;
34 double **a, **b, **c;
35 double *a_block, *b_block, *c_block;
36 double **res;
37 double *res_block;
38 double starttime, stoptime;
39
40 a = (double **) malloc(NRA*sizeof(double *)); /* matrix a to be multiplied */
41 b = (double **) malloc(NCA*sizeof(double *)); /* matrix b to be multiplied */
42 c = (double **) malloc(NRA*sizeof(double *)); /* result matrix c */
43
44 a_block = (double *) malloc(NRA*NCA*sizeof(double)); /* Storage for matrices */
45 b_block = (double *) malloc(NCA*NCB*sizeof(double));
46 c_block = (double *) malloc(NRA*NCB*sizeof(double));
47
48 /* Result matrix for the sequential algorithm */
49 res = (double **) malloc(NRA*sizeof(double *));
50 res_block = (double *) malloc(NRA*NCB*sizeof(double));
51
52 for (i=0; i<NRA; i++) /* Initialize pointers to a */
53 a[i] = a_block+i*NRA;
54
55 for (i=0; i<NCA; i++) /* Initialize pointers to b */
56 b[i] = b_block+i*NCA;
57
58 for (i=0; i<NRA; i++) /* Initialize pointers to c */
59 c[i] = c_block+i*NRA;
60
61 for (i=0; i<NRA; i++) /* Initialize pointers to res */
62 res[i] = res_block+i*NRA;
63
64 /* A static allocation of the matrices would be done like this */
65 /* double a[NRA][NCA], b[NCA][NCB], c[NRA][NCB]; */
66
67 /*** Spawn a parallel region explicitly scoping all variables ***/
68#pragma omp parallel shared(a,b,c,nthreads) private(tid,i,j,k) num_threads(NR_THREADS)
69 {
70 tid = omp_get_thread_num();
71 if (tid == 0) { /* Only thread 0 prints */
72 nthreads = omp_get_num_threads();
73 printf("Starting matrix multiplication with %d threads\n",nthreads);
74 printf("Initializing matrices...\n");
75 }
76 /*** Initialize matrices ***/
77#pragma omp for nowait /* No need to synchronize the threads before the */
78 for (i=0; i<NRA; i++) /* last matrix has been initialized */
79 for (j=0; j<NCA; j++)
80 a[i][j]= (double) (i+j);
81#pragma omp for nowait
82 for (i=0; i<NCA; i++)
83 for (j=0; j<NCB; j++)
84 b[i][j]= (double) (i*j);
85#pragma omp for /* We synchronize the threads after this */
86 for (i=0; i<NRA; i++)
87 for (j=0; j<NCB; j++)
88 c[i][j]= 0.0;
89
90 if (tid == 0) /* Thread zero measures time */
91 starttime = omp_get_wtime(); /* Master thread measures the execution time */
92
93 /* Do matrix multiply sharing iterations on outer loop */
94 /* If DEBUG is TRUE display who does which iterations */
95 /* printf("Thread %d starting matrix multiply...\n",tid); */
96#pragma omp for
97 for (i=0; i<NRA; i++) {
98 if (DEBUG) printf("Thread=%d did row=%d\n",tid,i);
99 for(j=0; j<NCB; j++) {
100 for (k=0; k<NCA; k++) {
101 c[i][j] += a[i][k] * b[k][j];
102 }
103 }
104 }
105
106 if (tid == 0) {
107 stoptime = omp_get_wtime();
108 printf("Time for parallel matrix multiplication: %3.2f s\n",
109 stoptime-starttime);
110 }
111 } /*** End of parallel region ***/
112
113 starttime = omp_get_wtime();
114 /* Do a sequential matrix multiplication and compare the results */
115 for (i=0; i<NRA; i++) {
116 for (j=0; j<NCB; j++) {
117 res[i][j] = 0.0;
118 for (k=0; k<NCA; k++)
119 res[i][j] += a[i][k]*b[k][j];
120 }
121 }
122 stoptime = omp_get_wtime();
123 printf("Time for sequential matrix multiplication: %3.2f s\n", stoptime-starttime);
124
125 /* Check that the results are the same as in the parallel solution.
126 Actually, you should not compare floating point values for equality like this
127 but instead compute the difference between the two values and check that it
128 is smaller than a very small value epsilon. However, since all values in the
129 matrices here are integer values, this will work.
130 */
131 for (i=0; i<NRA; i++) {
132 for (j=0; j<NCB; j++) {
133 if (res[i][j] == c[i][j]) {
134 /* Everything is OK if they are equal */
135 }
136 else {
137 printf("Different result %5.1f != %5.1f in %d %d\n ", res[i][j], c[i][j], i, j);
138 }
139 }
140 }
141
142 /* If DEBUG is true, print the results. Usa smaller matrices for this */
143 if (DEBUG) {
144 printf("Result Matrix:\n");
145 for (i=0; i<NRA; i++) {
146 for (j=0; j<NCB; j++)
147 printf("%6.1f ", c[i][j]);
148 printf("\n");
149 }
150 }
151
152 printf ("Done.\n");
153 exit(0);
154}
Note: See TracBrowser for help on using the repository browser.