| 1 | # include <stdlib.h>
|
|---|
| 2 | # include <stdio.h>
|
|---|
| 3 | # include <math.h>
|
|---|
| 4 | # include <omp.h>
|
|---|
| 5 |
|
|---|
| 6 | int main ( int argc, char *argv[] );
|
|---|
| 7 | void r8_mxm ( int l, int m, int n );
|
|---|
| 8 | double r8_uniform_01 ( int *seed );
|
|---|
| 9 |
|
|---|
| 10 | /******************************************************************************/
|
|---|
| 11 |
|
|---|
| 12 | int main ( int argc, char *argv[] )
|
|---|
| 13 |
|
|---|
| 14 | /******************************************************************************/
|
|---|
| 15 | /*
|
|---|
| 16 | Purpose:
|
|---|
| 17 |
|
|---|
| 18 | MAIN is the main program for MXM.
|
|---|
| 19 |
|
|---|
| 20 | Licensing:
|
|---|
| 21 |
|
|---|
| 22 | This code is distributed under the GNU LGPL license.
|
|---|
| 23 |
|
|---|
| 24 | Modified:
|
|---|
| 25 |
|
|---|
| 26 | 19 April 2009
|
|---|
| 27 |
|
|---|
| 28 | Author:
|
|---|
| 29 |
|
|---|
| 30 | John Burkardt
|
|---|
| 31 | */
|
|---|
| 32 | {
|
|---|
| 33 | int id;
|
|---|
| 34 | int l;
|
|---|
| 35 | int m;
|
|---|
| 36 | int n;
|
|---|
| 37 |
|
|---|
| 38 | printf ( "\n" );
|
|---|
| 39 | printf ( "MXM\n" );
|
|---|
| 40 | printf ( " C/OpenMP version.\n" );
|
|---|
| 41 | printf ( "\n" );
|
|---|
| 42 | printf ( " Matrix multiplication tests.\n" );
|
|---|
| 43 |
|
|---|
| 44 | printf ( "\n" );
|
|---|
| 45 | printf ( " Number of processors available = %d\n", omp_get_num_procs ( ) );
|
|---|
| 46 | printf ( " Number of threads = %d\n", omp_get_max_threads ( ) );
|
|---|
| 47 |
|
|---|
| 48 | l = 10;
|
|---|
| 49 | m = 10;
|
|---|
| 50 | n = 10;
|
|---|
| 51 |
|
|---|
| 52 | r8_mxm ( l, m, n );
|
|---|
| 53 | /*
|
|---|
| 54 | Terminate.
|
|---|
| 55 | */
|
|---|
| 56 | printf ( "\n" );
|
|---|
| 57 | printf ( "MXM:\n" );
|
|---|
| 58 | printf ( " Normal end of execution.\n" );
|
|---|
| 59 |
|
|---|
| 60 | return 0;
|
|---|
| 61 | }
|
|---|
| 62 | /******************************************************************************/
|
|---|
| 63 |
|
|---|
| 64 | void r8_mxm ( int l, int m, int n )
|
|---|
| 65 |
|
|---|
| 66 | /******************************************************************************/
|
|---|
| 67 | /*
|
|---|
| 68 | Purpose:
|
|---|
| 69 |
|
|---|
| 70 | R8_MXM carries out a matrix-matrix multiplication in R8 arithmetic.
|
|---|
| 71 |
|
|---|
| 72 | Discussion:
|
|---|
| 73 |
|
|---|
| 74 | A(LxN) = B(LxM) * C(MxN).
|
|---|
| 75 |
|
|---|
| 76 | Licensing:
|
|---|
| 77 |
|
|---|
| 78 | This code is distributed under the GNU LGPL license.
|
|---|
| 79 |
|
|---|
| 80 | Modified:
|
|---|
| 81 |
|
|---|
| 82 | 13 February 2008
|
|---|
| 83 |
|
|---|
| 84 | Author:
|
|---|
| 85 |
|
|---|
| 86 | John Burkardt
|
|---|
| 87 |
|
|---|
| 88 | Parameters:
|
|---|
| 89 |
|
|---|
| 90 | Input, int L, M, N, the dimensions that specify the sizes of the
|
|---|
| 91 | A, B, and C matrices.
|
|---|
| 92 | */
|
|---|
| 93 | {
|
|---|
| 94 | double *a;
|
|---|
| 95 | double *b;
|
|---|
| 96 | double *c;
|
|---|
| 97 | int i;
|
|---|
| 98 | int j;
|
|---|
| 99 | int k;
|
|---|
| 100 | int ops;
|
|---|
| 101 | double rate;
|
|---|
| 102 | int seed;
|
|---|
| 103 | double time_begin;
|
|---|
| 104 | double time_elapsed;
|
|---|
| 105 | double time_stop;
|
|---|
| 106 | /*
|
|---|
| 107 | Allocate the matrices.
|
|---|
| 108 | */
|
|---|
| 109 | a = ( double * ) malloc ( l * n * sizeof ( double ) );
|
|---|
| 110 | b = ( double * ) malloc ( l * m * sizeof ( double ) );
|
|---|
| 111 | c = ( double * ) malloc ( m * n * sizeof ( double ) );
|
|---|
| 112 | /*
|
|---|
| 113 | Assign values to the B and C matrices.
|
|---|
| 114 | */
|
|---|
| 115 | seed = 123456789;
|
|---|
| 116 |
|
|---|
| 117 | for ( k = 0; k < l * m; k++ )
|
|---|
| 118 | {
|
|---|
| 119 | b[k] = r8_uniform_01 ( &seed );
|
|---|
| 120 | }
|
|---|
| 121 |
|
|---|
| 122 | for ( k = 0; k < m * n; k++ )
|
|---|
| 123 | {
|
|---|
| 124 | c[k] = r8_uniform_01 ( &seed );
|
|---|
| 125 | }
|
|---|
| 126 | /*
|
|---|
| 127 | Compute A = B * C.
|
|---|
| 128 | */
|
|---|
| 129 | time_begin = omp_get_wtime ( );
|
|---|
| 130 |
|
|---|
| 131 | # pragma omp parallel \
|
|---|
| 132 | shared ( a, b, c, l, m, n ) \
|
|---|
| 133 | private ( i, j, k )
|
|---|
| 134 |
|
|---|
| 135 | # pragma omp for
|
|---|
| 136 | for ( j = 0; j < n; j++)
|
|---|
| 137 | {
|
|---|
| 138 | for ( i = 0; i < l; i++ )
|
|---|
| 139 | {
|
|---|
| 140 | a[i+j*l] = 0.0;
|
|---|
| 141 | for ( k = 0; k < m; k++ )
|
|---|
| 142 | {
|
|---|
| 143 | a[i+j*l] = a[i+j*l] + b[i+k*l] * c[k+j*m];
|
|---|
| 144 | }
|
|---|
| 145 | }
|
|---|
| 146 | }
|
|---|
| 147 | time_stop = omp_get_wtime ( );
|
|---|
| 148 | /*
|
|---|
| 149 | Report.
|
|---|
| 150 | */
|
|---|
| 151 | ops = l * n * ( 2 * m );
|
|---|
| 152 | time_elapsed = time_stop - time_begin;
|
|---|
| 153 | rate = ( double ) ( ops ) / time_elapsed / 1000000.0;
|
|---|
| 154 |
|
|---|
| 155 | printf ( "\n" );
|
|---|
| 156 | printf ( "R8_MXM matrix multiplication timing.\n" );
|
|---|
| 157 | printf ( " A(LxN) = B(LxM) * C(MxN).\n" );
|
|---|
| 158 | printf ( " L = %d\n", l );
|
|---|
| 159 | printf ( " M = %d\n", m );
|
|---|
| 160 | printf ( " N = %d\n", n );
|
|---|
| 161 | printf ( " Floating point OPS roughly %d\n", ops );
|
|---|
| 162 | printf ( " Elapsed time dT = %f\n", time_elapsed );
|
|---|
| 163 | printf ( " Rate = MegaOPS/dT = %f\n", rate );
|
|---|
| 164 |
|
|---|
| 165 | free ( a );
|
|---|
| 166 | free ( b );
|
|---|
| 167 | free ( c );
|
|---|
| 168 |
|
|---|
| 169 | return;
|
|---|
| 170 | }
|
|---|
| 171 | /******************************************************************************/
|
|---|
| 172 |
|
|---|
| 173 | double r8_uniform_01 ( int *seed )
|
|---|
| 174 |
|
|---|
| 175 | /******************************************************************************/
|
|---|
| 176 | /*
|
|---|
| 177 | Purpose:
|
|---|
| 178 |
|
|---|
| 179 | R8_UNIFORM_01 is a unit pseudorandom R8.
|
|---|
| 180 |
|
|---|
| 181 | Discussion:
|
|---|
| 182 |
|
|---|
| 183 | This routine implements the recursion
|
|---|
| 184 |
|
|---|
| 185 | seed = 16807 * seed mod ( 2**31 - 1 )
|
|---|
| 186 | unif = seed / ( 2**31 - 1 )
|
|---|
| 187 |
|
|---|
| 188 | The integer arithmetic never requires more than 32 bits,
|
|---|
| 189 | including a sign bit.
|
|---|
| 190 |
|
|---|
| 191 | Licensing:
|
|---|
| 192 |
|
|---|
| 193 | This code is distributed under the GNU LGPL license.
|
|---|
| 194 |
|
|---|
| 195 | Modified:
|
|---|
| 196 |
|
|---|
| 197 | 11 August 2004
|
|---|
| 198 |
|
|---|
| 199 | Author:
|
|---|
| 200 |
|
|---|
| 201 | John Burkardt
|
|---|
| 202 |
|
|---|
| 203 | Reference:
|
|---|
| 204 |
|
|---|
| 205 | Paul Bratley, Bennett Fox, Linus Schrage,
|
|---|
| 206 | A Guide to Simulation,
|
|---|
| 207 | Springer Verlag, pages 201-202, 1983.
|
|---|
| 208 |
|
|---|
| 209 | Bennett Fox,
|
|---|
| 210 | Algorithm 647:
|
|---|
| 211 | Implementation and Relative Efficiency of Quasirandom
|
|---|
| 212 | Sequence Generators,
|
|---|
| 213 | ACM Transactions on Mathematical Software,
|
|---|
| 214 | Volume 12, Number 4, pages 362-376, 1986.
|
|---|
| 215 |
|
|---|
| 216 | Parameters:
|
|---|
| 217 |
|
|---|
| 218 | Input/output, int *SEED, a seed for the random number generator.
|
|---|
| 219 |
|
|---|
| 220 | Output, double R8_UNIFORM_01, a new pseudorandom variate, strictly between
|
|---|
| 221 | 0 and 1.
|
|---|
| 222 | */
|
|---|
| 223 | {
|
|---|
| 224 | int k;
|
|---|
| 225 | double r;
|
|---|
| 226 |
|
|---|
| 227 | k = *seed / 127773;
|
|---|
| 228 |
|
|---|
| 229 | *seed = 16807 * ( *seed - k * 127773 ) - k * 2836;
|
|---|
| 230 |
|
|---|
| 231 | if ( *seed < 0 )
|
|---|
| 232 | {
|
|---|
| 233 | *seed = *seed + 2147483647;
|
|---|
| 234 | }
|
|---|
| 235 |
|
|---|
| 236 | r = ( double ) ( *seed ) * 4.656612875E-10;
|
|---|
| 237 |
|
|---|
| 238 | return r;
|
|---|
| 239 | }
|
|---|
| 240 |
|
|---|
| 241 |
|
|---|