228077140e954b75e7cdf92fd347bf3b675b6fe9
[riscv-tests.git] / mt / aj_matmul / matmul_mi.c
1 //**************************************************************************
2 // Multi-threaded Matrix Multiply benchmark
3 //--------------------------------------------------------------------------
4 // TA : Christopher Celio
5 // Student:
6 //
7 //
8 // This benchmark multiplies two 2-D arrays together and writes the results to
9 // a third vector. The input data (and reference data) should be generated
10 // using the matmul_gendata.pl perl script and dumped to a file named
11 // dataset.h.
12
13
14 // print out arrays, etc.
15 //#define DEBUG
16
17 //--------------------------------------------------------------------------
18 // Includes
19
20 #include <string.h>
21 #include <stdlib.h>
22 #include <stdio.h>
23
24
25 //--------------------------------------------------------------------------
26 // Input/Reference Data
27
28 typedef float data_t;
29 #include "dataset.h"
30
31
32 //--------------------------------------------------------------------------
33 // Basic Utilities and Multi-thread Support
34
35 __thread unsigned long coreid;
36 unsigned long ncores;
37
38 #include "util.h"
39
40 #define stringify_1(s) #s
41 #define stringify(s) stringify_1(s)
42 #define stats(code) do { \
43 unsigned long _c = -rdcycle(), _i = -rdinstret(); \
44 code; \
45 _c += rdcycle(), _i += rdinstret(); \
46 if (coreid == 0) \
47 printf("%s: %ld cycles, %ld.%ld cycles/iter, %ld.%ld CPI\n", \
48 stringify(code), _c, _c/DIM_SIZE/DIM_SIZE/DIM_SIZE, 10*_c/DIM_SIZE/DIM_SIZE/DIM_SIZE%10, _c/_i, 10*_c/_i%10); \
49 } while(0)
50
51
52 //--------------------------------------------------------------------------
53 // Helper functions
54
55 void printArray( char name[], int n, data_t arr[] )
56 {
57 int i;
58 if (coreid != 0)
59 return;
60
61 printf( " %10s :", name );
62 for ( i = 0; i < n; i++ )
63 printf( " %3ld ", (long) arr[i] );
64 printf( "\n" );
65 }
66
67 void __attribute__((noinline)) verify(size_t n, const data_t* test, const data_t* correct)
68 {
69 if (coreid != 0)
70 return;
71
72 size_t i;
73 for (i = 0; i < n; i++)
74 {
75 if (test[i] != correct[i])
76 {
77 printf("FAILED test[%d]= %3ld, correct[%d]= %3ld\n",
78 i, (long)test[i], i, (long)correct[i]);
79 exit(-1);
80 }
81 }
82
83 return;
84 }
85
86 void matrix_sub(int size, data_t A[], data_t B[], data_t C[]) {
87 if (coreid != 0)
88 return;
89
90 for(int i = 0; i < size; i++){
91 C[i] = A[i] + B[i];
92 }
93 }
94
95 void matrix_add(int size, data_t A[], data_t B[], data_t C[]) {
96 if (coreid != 0)
97 return;
98
99 for(int i = 0; i < size; i++){
100 C[i] = A[i] - B[i];
101 }
102 }
103
104 void strassen_mult(int dime, const data_t sA[], const data_t sB[], data_t sC[]) {
105
106 if (coreid != 0)
107 return;
108
109 int height, width;
110 int sub_size = dime*dime/4;
111
112 // data_t A_11[sub_size], B_11[sub_size], C_11[sub_size],
113 // A_12[sub_size], B_12[sub_size], C_12[sub_size],
114 // A_21[sub_size], B_21[sub_size], C_21[sub_size],
115 // A_22[sub_size], B_22[sub_size], C_22[sub_size];
116
117 data_t *A_11 = malloc(sub_size*sizeof(data_t));
118 data_t *A_12 = malloc(sub_size*sizeof(data_t));
119 data_t *A_21 = malloc(sub_size*sizeof(data_t));
120 data_t *A_22 = malloc(sub_size*sizeof(data_t));
121 data_t *B_11 = malloc(sub_size*sizeof(data_t));
122 data_t *B_12 = malloc(sub_size*sizeof(data_t));
123 data_t *B_21 = malloc(sub_size*sizeof(data_t));
124 data_t *B_22 = malloc(sub_size*sizeof(data_t));
125
126 for(height=0; height < dime/2; height++) {
127 for(width= 0; width < dime/2; width++) {
128 A_11[width+(height*dime/2)] = sA[width + height*dime];
129 B_11[width+(height*dime/2)] = sB[width + height*dime];
130
131 A_12[width+(height*dime/2)] = sA[dime/2 + width + height*dime];
132 B_12[width+(height*dime/2)] = sB[dime/2 + width + height*dime];
133
134 A_21[width+(height*dime/2)] = sA[(dime*dime)/2 + width + height*dime];
135 B_21[width+(height*dime/2)] = sB[(dime*dime)/2 + width + height*dime];
136
137 A_22[width+(height*dime/2)] = sA[(dime*dime)/2 + dime/2 + width + height*dime];
138 B_22[width+(height*dime/2)] = sB[(dime*dime)/2 + dime/2 + width + height*dime];
139 }
140 }
141
142 // data_t H_1[sub_size], H_2[sub_size], H_3[sub_size], H_4[sub_size], H_5[sub_size],
143 // H_6[sub_size], H_7[sub_size], H_8[sub_size], H_9[sub_size], H_10[sub_size],
144 // H_11[sub_size], H_12[sub_size], H_13[sub_size], H_14[sub_size],
145 // H_15[sub_size], H_16[sub_size], H_17[sub_size], H_18[sub_size];
146
147 data_t *H_1 = malloc(sub_size*sizeof(data_t));
148 data_t *H_2 = malloc(sub_size*sizeof(data_t));
149 data_t *H_3 = malloc(sub_size*sizeof(data_t));
150 data_t *H_4 = malloc(sub_size*sizeof(data_t));
151 data_t *H_5 = malloc(sub_size*sizeof(data_t));
152 data_t *H_6 = malloc(sub_size*sizeof(data_t));
153 data_t *H_7 = malloc(sub_size*sizeof(data_t));
154 data_t *H_8 = malloc(sub_size*sizeof(data_t));
155 data_t *H_9 = malloc(sub_size*sizeof(data_t));
156 data_t *H_10 = malloc(sub_size*sizeof(data_t));
157
158 matrix_add(sub_size, A_11, A_22, H_1); //Helper1
159 matrix_add(sub_size, B_11, B_22, H_2); //Helper2
160 matrix_add(sub_size, A_21, A_22, H_3); //Helper3
161 matrix_sub(sub_size, B_12, B_22, H_4); //Helper4
162 matrix_sub(sub_size, B_21, B_11, H_5); //Helper5
163 matrix_add(sub_size, A_11, A_12, H_6); //Helper6
164 matrix_sub(sub_size, A_21, A_11, H_7); //Helper7
165 matrix_add(sub_size, B_11, B_12, H_8); //Helper8
166 matrix_sub(sub_size, A_12, A_22, H_9); //Helper9
167 matrix_add(sub_size, B_21, B_22, H_10); //Helper10
168
169 free(A_12);
170 free(A_21);
171 free(B_12);
172 free(B_21);
173
174 A_12 = NULL;
175 A_21 = NULL;
176 B_12 = NULL;
177 B_21 = NULL;
178
179 // data_t M_1[sub_size], M_2[sub_size], M_3[sub_size], M_4[sub_size],
180 // M_5[sub_size], M_6[sub_size], M_7[sub_size];
181
182 data_t *M_1 = malloc(sub_size*sizeof(data_t));
183 data_t *M_2 = malloc(sub_size*sizeof(data_t));
184 data_t *M_3 = malloc(sub_size*sizeof(data_t));
185 data_t *M_4 = malloc(sub_size*sizeof(data_t));
186 data_t *M_5 = malloc(sub_size*sizeof(data_t));
187 data_t *M_6 = malloc(sub_size*sizeof(data_t));
188 data_t *M_7 = malloc(sub_size*sizeof(data_t));
189
190 if (sub_size == 1) {
191 M_1[0] = H_1[0]*H_2[0];
192 M_2[0] = H_3[0]*B_11[0];
193 M_3[0] = A_11[0]*H_4[0];
194 M_4[0] = A_22[0]*H_5[0];
195 M_5[0] = H_6[0]*B_22[0];
196 M_6[0] = H_7[0]*H_8[0];
197 M_7[0] = H_9[0]*H_10[0];
198 } else {
199 strassen_mult(dime/2, H_1, H_2, M_1);
200 strassen_mult(dime/2, H_3, B_11, M_2);
201 strassen_mult(dime/2, A_11, H_4, M_3);
202 strassen_mult(dime/2, A_22, H_5, M_4);
203 strassen_mult(dime/2, H_6, B_22, M_5);
204 strassen_mult(dime/2, H_7, H_8, M_6);
205 strassen_mult(dime/2, H_9, H_10, M_7);
206 }
207
208 free(A_11);
209 free(A_22);
210 free(B_11);
211 free(B_22);
212
213 A_11 = NULL;
214 A_22 = NULL;
215 B_11 = NULL;
216 B_22 = NULL;
217
218 free(H_1);
219 free(H_2);
220 free(H_3);
221 free(H_4);
222 free(H_5);
223 free(H_6);
224 free(H_7);
225 free(H_8);
226 free(H_9);
227 free(H_10);
228
229 H_1 = NULL;
230 H_2 = NULL;
231 H_3 = NULL;
232 H_4 = NULL;
233 H_5 = NULL;
234 H_6 = NULL;
235 H_7 = NULL;
236 H_8 = NULL;
237 H_9 = NULL;
238 H_10 = NULL;
239
240 data_t *H_11 = malloc(sub_size*sizeof(data_t));
241 data_t *H_12 = malloc(sub_size*sizeof(data_t));
242 data_t *H_13 = malloc(sub_size*sizeof(data_t));
243 data_t *H_14 = malloc(sub_size*sizeof(data_t));
244
245 data_t *C_11 = malloc(sub_size*sizeof(data_t));
246 data_t *C_12 = malloc(sub_size*sizeof(data_t));
247 data_t *C_21 = malloc(sub_size*sizeof(data_t));
248 data_t *C_22 = malloc(sub_size*sizeof(data_t));
249
250 matrix_add(sub_size, M_1, M_4, H_11);
251 matrix_add(sub_size, M_5, M_7, H_12);
252 matrix_sub(sub_size, H_11, H_12, C_11);
253
254 matrix_add(sub_size, M_3, M_5, C_12);
255
256 matrix_add(sub_size, M_2, M_4, C_21);
257
258 matrix_sub(sub_size, M_1, M_2, H_13);
259 matrix_add(sub_size, M_3, M_6, H_14);
260 matrix_add(sub_size, H_13, H_14, C_22);
261
262 free(H_11);
263 free(H_12);
264 free(H_13);
265 free(H_14);
266
267 H_11 = NULL;
268 H_12 = NULL;
269 H_13 = NULL;
270 H_14 = NULL;
271
272
273 for(height=0; height < dime/2; height++) {
274 for(width= 0; width < dime/2; width++) {
275 sC[width + height*dime] = C_11[width+(height*dime/2)];
276 sC[dime/2 + width + height*dime] = C_12[width+(height*dime/2)];
277 sC[(dime*dime)/2 + width + height*dime] = C_21[width+(height*dime/2)];
278 sC[(dime*dime)/2 + dime/2 + width + height*dime] = C_22[width+(height*dime/2)];
279 }
280 }
281
282 free(C_11);
283 free(C_12);
284 free(C_21);
285 free(C_22);
286
287 C_11 = NULL;
288 C_12 = NULL;
289 C_21 = NULL;
290 C_22 = NULL;
291
292 }
293
294 //--------------------------------------------------------------------------
295 // matmul function
296
297 // single-thread, naive version
298 void __attribute__((noinline)) matmul_naive(const int lda, const data_t A[], const data_t B[], data_t C[] )
299 {
300 int i, j, k;
301
302 if (coreid > 0)
303 return;
304
305 for ( i = 0; i < lda; i++ )
306 for ( j = 0; j < lda; j++ )
307 {
308 for ( k = 0; k < lda; k++ )
309 {
310 C[i + j*lda] += A[j*lda + k] * B[k*lda + i];
311 }
312 }
313
314 }
315
316
317
318 void __attribute__((noinline)) matmul(const int lda, const data_t A[], const data_t B[], data_t C[] )
319 {
320
321 // ***************************** //
322 // **** ADD YOUR CODE HERE ***** //
323 // ***************************** //
324 //
325 // feel free to make a separate function for MI and MSI versions.
326
327 if (coreid > 0)
328 return;
329
330 strassen_mult(lda, A, B, C);
331
332 }
333
334 //--------------------------------------------------------------------------
335 // Main
336 //
337 // all threads start executing thread_entry(). Use their "coreid" to
338 // differentiate between threads (each thread is running on a separate core).
339
340 void thread_entry(int cid, int nc)
341 {
342 coreid = cid;
343 ncores = nc;
344
345 // static allocates data in the binary, which is visible to both threads
346 static data_t results_data[ARRAY_SIZE];
347
348
349 // // Execute the provided, naive matmul
350 // barrier();
351 // stats(matmul_naive(DIM_SIZE, input1_data, input2_data, results_data); barrier());
352 //
353 //
354 // // verify
355 // verify(ARRAY_SIZE, results_data, verify_data);
356 //
357 // // clear results from the first trial
358 // size_t i;
359 // if (coreid == 0)
360 // for (i=0; i < ARRAY_SIZE; i++)
361 // results_data[i] = 0;
362 // barrier();
363
364
365 // Execute your faster matmul
366 barrier();
367 stats(matmul(DIM_SIZE, input1_data, input2_data, results_data); barrier());
368
369 #ifdef DEBUG
370 printArray("results:", ARRAY_SIZE, results_data);
371 printArray("verify :", ARRAY_SIZE, verify_data);
372 #endif
373
374 // verify
375 verify(ARRAY_SIZE, results_data, verify_data);
376 barrier();
377
378 exit(0);
379 }
380