-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathdgemm-blocked-simple-tests.c
144 lines (128 loc) · 5.84 KB
/
dgemm-blocked-simple-tests.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
#include <stdlib.h>
#ifndef _GNU_SOURCE
#define _GNU_SOURCE = 1 // for asprintf
#endif
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <float.h> // For: DBL_EPSILON
#include <math.h> // For: fabs
#include "unit-test-framework.h"
#include "matrix-storage.h"
#include "dgemm-blocked-simple.h"
/* reference_dgemm wraps a call to the BLAS-3 routine DGEMM, via the standard FORTRAN interface - hence the reference semantics. */
#define DGEMM dgemm_
extern void DGEMM (char*, char*, int*, int*, int*, double*, double*, int*, double*, int*, double*, double*, int*);
void reference_dgemm (int N, double ALPHA, double* A, double* B, double* C)
{
char TRANSA = 'N';
char TRANSB = 'N';
int M = N;
int K = N;
double BETA = 1.;
int LDA = N;
int LDB = N;
int LDC = N;
DGEMM(&TRANSA, &TRANSB, &M, &N, &K, &ALPHA, A, &LDA, B, &LDB, &BETA, C, &LDC);
}
extern const char* dgemm_desc;
extern void square_dgemm (int, double*, double*, double*);
/* Assert that square_dgemm gives approximately the same value as the reference
* implementation for a * b.
*/
char* assert_dgemm_works(int matrix_size, double* a, double* b) {
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* reference_result = make_arbitrary_matrix(format);
double* actual_result = make_arbitrary_matrix(format);
reference_dgemm(matrix_size, 1, a, b, reference_result);
square_dgemm(matrix_size, a, b, actual_result);
return assert_matrix_approx_equals(reference_result, format, actual_result, format, 3.0*DBL_EPSILON*matrix_size);
}
/* Assert that square_dgemm_with_block_size gives approximately the same value as
* the reference implementation for a * b.
*/
char* assert_dgemm_with_block_size_works(int matrix_size, double* a, double* b, int block_size) {
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* reference_result = make_arbitrary_matrix(format);
double* actual_result = copy(reference_result, format);
reference_dgemm(matrix_size, 1, a, b, reference_result);
square_dgemm_with_block_size(matrix_size, a, b, actual_result, block_size);
return assert_matrix_approx_equals(reference_result, format, actual_result, format, 3.0*DBL_EPSILON*matrix_size);
}
///////////////////////////////////////////////////////////////////////////////
// Begin tests
///////////////////////////////////////////////////////////////////////////////
static char* test_dgemm_args_not_modified() {
square_matrix_storage_format* format = square_matrix_storage_format_new(10, COLUMN_MAJOR, 0);
double* a = make_rand(format);
double* a_copy = malloc(num_elements(format) * sizeof(double));
memcpy(a_copy, a, num_elements(format) * sizeof(double));
double* b = make_rand(format);
double* b_copy = malloc(num_elements(format) * sizeof(double));
memcpy(b_copy, b, num_elements(format) * sizeof(double));
double* c = make_rand(format);
square_dgemm_with_block_size(format->matrix_size, a, b, c, 2);
return both(
assert_matrix_equals(a, format, a_copy, format),
assert_matrix_equals(b, format, b_copy, format));
}
static char* test_dgemm_left_identity() {
int matrix_size = 10;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* i = make_identity(format);
double* m = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, i, m, 2);
}
static char* test_dgemm_right_identity() {
int matrix_size = 6;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* i = make_identity(format);
double* m = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, m, i, 2);
}
static char* test_dgemm_random() {
int matrix_size = 10;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* a = make_rand(format);
double* b = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, a, b, 2);
}
static char* test_dgemm_small_block() {
int matrix_size = 10;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* a = make_rand(format);
double* b = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, a, b, 1);
}
static char* test_dgemm_large_block() {
int matrix_size = 10;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* a = make_rand(format);
double* b = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, a, b, 10);
}
static char* test_dgemm_unaligned() {
int matrix_size = 10;
square_matrix_storage_format* format = square_matrix_storage_format_new(matrix_size, COLUMN_MAJOR, 0);
double* a = make_rand(format);
double* b = make_rand(format);
return assert_dgemm_with_block_size_works(matrix_size, a, b, 3);
}
///////////////////////////////////////////////////////////////////////////////
// End tests
///////////////////////////////////////////////////////////////////////////////
int main (int argc, char **argv) {
printf ("Running tests for algorithm with description: %s\n", dgemm_desc);
test_definition* tests[] = {
test("multiplying without changing input arguments", test_dgemm_args_not_modified),
test("multiplying on the left by the identity", test_dgemm_left_identity),
test("multiplying on the right by the identity", test_dgemm_right_identity),
test("multiplying random matrices", test_dgemm_random),
test("multiplying random matrices with a tiny block size", test_dgemm_small_block),
test("multiplying random matrices with a large block size", test_dgemm_large_block),
test("multiplying random matrices with a matrix size that does not align to the block size", test_dgemm_unaligned),
NULL
};
run_tests(true, tests);
return 0;
}