-
Notifications
You must be signed in to change notification settings - Fork 30
/
matrixMultiply.c
149 lines (127 loc) · 4.53 KB
/
matrixMultiply.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
/* To save you time, we are including all 6 variants of the loop ordering
as separate functions and then calling them using function pointers.
The reason for having separate functions that are nearly identical is
to avoid counting any extraneous processing towards the computation
time. This includes I/O accesses (printf) and conditionals (if/switch).
I/O accesses are slow and conditional/branching statements could
unfairly bias results (lower cases in switches must run through more
case statements on each iteration).
*/
void multMat1( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is ijk loop order. */
for( i = 0; i < n; i++ ) {
for( j = 0; j < n; j++ ) {
for( k = 0; k < n; k++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
void multMat2( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is ikj loop order. */
for( i = 0; i < n; i++ ) {
for( k = 0; k < n; k++ ) {
for( j = 0; j < n; j++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
void multMat3( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is jik loop order. */
for( j = 0; j < n; j++ ) {
for( i = 0; i < n; i++ ) {
for( k = 0; k < n; k++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
void multMat4( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is jki loop order. */
for( j = 0; j < n; j++ ) {
for( k = 0; k < n; k++ ) {
for( i = 0; i < n; i++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
void multMat5( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is kij loop order. */
for( k = 0; k < n; k++ ) {
for( i = 0; i < n; i++ ) {
for( j = 0; j < n; j++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
void multMat6( int n, float *A, float *B, float *C ) {
int i,j,k;
/* This is kji loop order. */
for( k = 0; k < n; k++ ) {
for( j = 0; j < n; j++ ) {
for( i = 0; i < n; i++ ) {
C[i+j*n] += A[i+k*n]*B[k+j*n];
}
}
}
}
/* defaults to Part 1. pass it any argument for Part 2. */
/* uses timing features from sys/time.h that you haven't seen before */
int main( int argc, char **argv ) {
int nmax = 1000,i,n;
void (*orderings[])(int,float *,float *,float *) = {&multMat1,&multMat2,&multMat3,&multMat4,&multMat5,&multMat6};
char *names[] = {"ijk","ikj","jik","jki","kij","kji"};
float *A = (float *)malloc( nmax*nmax * sizeof(float));
float *B = (float *)malloc( nmax*nmax * sizeof(float));
float *C = (float *)malloc( nmax*nmax * sizeof(float));
struct timeval start, end;
if( argv[1] ) {
printf("Running Part B...\n\n");
/* fill matrices with random numbers */
for( i = 0; i < nmax*nmax; i++ ) A[i] = drand48()*2-1;
for( i = 0; i < nmax*nmax; i++ ) B[i] = drand48()*2-1;
for( i = 0; i < nmax*nmax; i++ ) C[i] = drand48()*2-1;
for( i = 0; i < 6; i++) {
/* multiply matrices and measure the time */
gettimeofday( &start, NULL );
(*orderings[i])( nmax, A, B, C );
gettimeofday( &end, NULL );
/* convert time to Gflop/s */
double seconds = (end.tv_sec - start.tv_sec) + 1.0e-6 * (end.tv_usec - start.tv_usec);
double Gflops = 2e-9*nmax*nmax*nmax/seconds;
printf( "%s:\tn = %d, %.3f Gflop/s\n", names[i], nmax, Gflops );
}
} else {
printf("Running Part A...\n\n");
for( n = 10; n <= nmax; n = n<nmax && n+1+n/3>nmax ? nmax : n+1+n/3 ) {
/* fill matrices with random numbers */
for( i = 0; i < n*n; i++ ) A[i] = drand48()*2-1;
for( i = 0; i < n*n; i++ ) B[i] = drand48()*2-1;
for( i = 0; i < n*n; i++ ) C[i] = drand48()*2-1;
/* multiply matrices and measure the time */
gettimeofday( &start, NULL );
multMat1( n, A, B, C );
gettimeofday( &end, NULL );
/* convert time to Gflop/s */
double seconds = (end.tv_sec - start.tv_sec) + 1.0e-6 * (end.tv_usec - start.tv_usec);
double Gflops = 2e-9*n*n*n/seconds;
printf( "n = %d, %.3f Gflop/s\n", n, Gflops );
}
}
free( A );
free( B );
free( C );
printf("\n\n");
return 0;
}