# include # include # include int main ( int argc, char *argv[] ); double cpu_time ( ); double *matgen ( int m, int n, int *seed ); double mxm_ijk ( int n1, int n2, int n3, double b[], double c[] ); double mxm_ikj ( int n1, int n2, int n3, double b[], double c[] ); double mxm_jik ( int n1, int n2, int n3, double b[], double c[] ); double mxm_jki ( int n1, int n2, int n3, double b[], double c[] ); double mxm_kij ( int n1, int n2, int n3, double b[], double c[] ); double mxm_kji ( int n1, int n2, int n3, double b[], double c[] ); void timestamp ( ); //**************************************************************************** int main ( int argc, char *argv[] ) //**************************************************************************** // // Purpose: // // MAIN is the main program for MXM. // // Discussion: // // MXV computes a matrix-matrix product in a number of ways, and reports // the elapsed CPU time. // // The multiplication carried out is // // A(1:N1,1:N3) = B(1:N1,1:N2) * C(1:N2,1:N3) // // where B and C are real double precision matrices whose entries // are assigned randomly. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 08 October 2010 // // Author: // // John Burkardt // // Usage: // // mxm n1 n2 n3 // // Parameters: // // Command line argument, int N1, N2, N3, defines the number of // rows and columns in the two matrices. // { double *b; double *c; double cpu_seconds; int flop_count; double mflops; int n1; int n2; int n3; int seed; double time_estimate; timestamp ( ); printf ( "\n" ); printf ( "MXM:\n" ); printf ( " C version\n" ); printf ( " Compute matrix-matrix product A = B * C\n" ); // // Get N1. // if ( 1 < argc ) { n1 = atoi ( argv[1] ); } else { printf ( "\n" ); printf ( " Enter N1, the number of rows in B.\n" ); scanf ( "%d", &n1 ); } // // Get N2. // if ( 2 < argc ) { n2 = atoi ( argv[2] ); } else { printf ( "\n" ); printf ( " Enter N2, the number of columns in B and rows in C.\n" ); scanf ( "%d", &n2 ); } // // Get N3. // if ( 3 < argc ) { n3 = atoi ( argv[3] ); } else { printf ( "\n" ); printf ( " Enter N3, the number of columns in C.\n" ); scanf ( "%d", &n3 ); } // // Record the amount of work. // Each of the N1 * N3 entries of A requires N2 multiplies and N2 adds. // flop_count = 2 * n1 * n2 * n3; printf ( "\n" ); printf ( " Matrix B is %d by %d\n", n1, n2 ); printf ( " Matrix C is %d by %d\n", n2, n3 ); printf ( " Matrix A will be %d by %d\n", n1, n3 ); printf ( "\n" ); printf ( " Number of floating point operations = %d\n", flop_count ); time_estimate = ( double ) ( flop_count ) / 2.6E+09; printf ( " Estimated CPU time is %f seconds.\n", time_estimate ); // // Set B and C. // seed = 1325; b = matgen ( n1, n2, &seed ); c = matgen ( n2, n3, &seed ); printf ( "\n" ); printf ( " Method Cpu Seconds MegaFlopS\n" ); printf ( " ------ -------------- --------------\n" ); // // IJK // cpu_seconds = mxm_ijk ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " IJK %14f %14f\n", cpu_seconds, mflops ); // // IKJ // cpu_seconds = mxm_ikj ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " IKJ %14f %14f\n", cpu_seconds, mflops ); // // JIK // cpu_seconds = mxm_jik ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " JIK %14f %14f\n", cpu_seconds, mflops ); // // JKI // cpu_seconds = mxm_jki ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " JKI %14f %14f\n", cpu_seconds, mflops ); // // KIJ // cpu_seconds = mxm_kij ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " KIJ %14f %14f\n", cpu_seconds, mflops ); // // KJI // cpu_seconds = mxm_kji ( n1, n2, n3, b, c ); if ( 0.0 < cpu_seconds ) { mflops = ( double ) ( flop_count ) / cpu_seconds / 1000000.0; } else { mflops = -1.0; } printf ( " KJI %14f %14f\n", cpu_seconds, mflops ); // // Deallocate arrays. // free ( b ); free ( c ); // // Terminate. // printf ( "\n" ); printf ( "MXM:\n" ); printf ( " Normal end of execution.\n" ); printf ( "\n" ); timestamp ( ); return 0; } //**************************************************************************** double cpu_time ( void ) //**************************************************************************** // // Purpose: // // CPU_TIME returns the current reading on the CPU clock. // // Discussion: // // The CPU time measurements available through this routine are often // not very accurate. In some cases, the accuracy is no better than // a hundredth of a second. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 06 June 2005 // // Author: // // John Burkardt // // Parameters: // // Output, double CPU_TIME, the current reading of the CPU clock, in seconds. // { double value; value = ( double ) clock ( ) / ( double ) CLOCKS_PER_SEC; return value; } //**************************************************************************** double *matgen ( int m, int n, int *seed ) //**************************************************************************** // // Purpose: // // MATGEN generates a random matrix. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 09 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int M, N, the number of rows and columns // of the matrix. // // Input, int *SEED, a seed for the random number // generator. // // Output, double MATGEN[M*N], the matrix. // { double *a; int i; int j; a = ( double * ) malloc ( m * n * sizeof ( double ) ); // // Set the matrix A. // for ( j = 0;j < n; j++ ) { for ( i = 0; i < m; i++ ) { *seed = ( ( 3125 * *seed ) % 65536 ); a[i+j*m] = ( *seed - 32768.0 ) / 16384.0; } } return a; } //**************************************************************************** double mxm_ijk ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_IJK computes A = B * C using FOR I, FOR J, FOR K loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 09 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( i = 0; i < n1; i++ ) { for ( j = 0; j < n3; j++ ) { for ( k = 0; k < n2; k++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** double mxm_ikj ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_IKJ computes A = B * C using FOR I, FOR K, FOR J loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 07 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( i = 0; i < n1; i++ ) { for ( k = 0; k < n2; k++ ) { for ( j = 0; j < n3; j++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** double mxm_jik ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_JIK computes A = B * C using FOR J, FOR I, FOR K loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 07 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { for ( k = 0; k < n2; k++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** double mxm_jki ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_JKI computes A = B * C using FOR J, FOR K, FOR I loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 07 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( j = 0; j < n3; j++ ) { for ( k = 0; k < n2; k++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** double mxm_kij ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_KIJ computes A = B * C using FOR K, FOR I, FOR J loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 07 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( k = 0; k < n2; k++ ) { for ( i = 0; i < n1; i++ ) { for ( j = 0; j < n3; j++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** double mxm_kji ( int n1, int n2, int n3, double b[], double c[] ) //**************************************************************************** // // Purpose: // // MXM_KJI computes A = B * C using FOR K, FOR J, FOR I loops. // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 07 October 2010 // // Author: // // John Burkardt // // Parameters: // // Input, int N1, N2, N3, define the orders of the // matrices. // // Input, double B[N1*N2], C[N2*N3], the factor matrices. // // Output, double MXM_IJK, the elapsed CPU time. // { double *a; double cpu_seconds; int i; int j; int k; a = ( double * ) malloc ( n1 * n3 * sizeof ( double ) ); for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = 0.0; } } cpu_seconds = cpu_time ( ); for ( k = 0; k < n2; k++ ) { for ( j = 0; j < n3; j++ ) { for ( i = 0; i < n1; i++ ) { a[i+j*n1] = a[i+j*n1] + b[i+k*n1] * c[k+j*n2]; } } } cpu_seconds = cpu_time ( ) - cpu_seconds; free ( a ); return cpu_seconds; } //**************************************************************************** void timestamp ( ) //**************************************************************************** // // Purpose: // // TIMESTAMP prints the current YMDHMS date as a time stamp. // // Example: // // 31 May 2001 09:45:54 AM // // Licensing: // // This code is distributed under the MIT license. // // Modified: // // 24 September 2003 // // Author: // // John Burkardt // // Parameters: // // None // { # define TIME_SIZE 40 static char time_buffer[TIME_SIZE]; const struct tm *tm; time_t now; now = time ( NULL ); tm = localtime ( &now ); strftime ( time_buffer, TIME_SIZE, "%d %B %Y %I:%M:%S %p", tm ); printf ( "%s\n", time_buffer ); return; # undef TIME_SIZE }