updated smallscaling.c to build without C99 or C11
[platform/upstream/openblas.git] / benchmark / smallscaling.c
1 // run with OPENBLAS_NUM_THREADS=1 and OMP_NUM_THREADS=n
2 #include <math.h>
3 #include <stdlib.h>
4 #include <stdio.h>
5 #include <time.h>
6 #include <cblas.h>
7 #include <omp.h>
8 #define MIN_SIZE 5
9 #define MAX_SIZE 60
10 #define NB_SIZE 10
11
12 // number of loop for a 1x1 matrix. Lower it if the test is
13 // too slow on you computer.
14 #define NLOOP 2e7
15
16 typedef struct {
17     int matrix_size;
18     int n_loop;
19     void (* bench_func)();
20     void (* blas_func)();
21     void * (* create_matrix)(int size);
22 } BenchParam;
23
24 void * s_create_matrix(int size) {
25     float * r = malloc(size * sizeof(double));
26     int i;
27     for(i = 0; i < size; i++)
28         r[i] = 1e3 * i / size;
29     return r;
30 }
31
32 void * c_create_matrix(int size) {
33     float * r = malloc(size * 2 * sizeof(double));
34     int i;
35     for(i = 0; i < 2 * size; i++)
36         r[i] = 1e3 * i / size;
37     return r;
38 }
39
40 void * z_create_matrix(int size) {
41     double * r = malloc(size * 2 * sizeof(double));
42     int i;
43     for(i = 0; i < 2 * size; i++)
44         r[i] = 1e3 * i / size;
45     return r;
46 }
47
48 void * d_create_matrix(int size) {
49     double * r = malloc(size * sizeof(double));
50     int i;
51     for(i = 0; i < size; i++)
52         r[i] = 1e3 * i / size;
53     return r;
54 }
55
56 void trmv_bench(BenchParam * param)
57 {
58     int i, n;
59     int size = param->matrix_size;
60     n = param->n_loop / size;
61     int one = 1;
62     void * A = param->create_matrix(size * size);
63     void * y = param->create_matrix(size);
64     for(i = 0; i < n; i++) {
65         param->blas_func("U", "N", "N", &size, A, &size, y, &one);
66     }
67     free(A);
68     free(y);
69 }
70
71 void gemv_bench(BenchParam * param)
72 {
73     int i, n;
74     int size = param->matrix_size;
75     n = param->n_loop / size;
76     double v = 1.01;
77     int one = 1;
78     void * A = param->create_matrix(size * size);
79     void * y = param->create_matrix(size);
80     for(i = 0; i < n; i++) {
81         param->blas_func("N", &size, &size, &v, A, &size, y, &one, &v, y, &one);
82     }
83     free(A);
84     free(y);
85 }
86
87 void ger_bench(BenchParam * param) {
88     int i, n;
89     int size = param->matrix_size;
90     n = param->n_loop / size;
91     double v = 1.01;
92     int one = 1;
93     void * A = param->create_matrix(size * size);
94     void * y = param->create_matrix(size);
95     for(i = 0; i < n; i++) {
96         param->blas_func(&size, &size, &v, y, &one, y, &one, A, &size);
97     }
98     free(A);
99     free(y);
100 }
101
102 #ifndef _WIN32
103 void * pthread_func_wrapper(void * param) {
104     ((BenchParam *)param)->bench_func(param);
105     pthread_exit(NULL);
106 }
107 #endif
108
109 #define NB_TESTS 5
110 void * TESTS[4 * NB_TESTS] = {
111     trmv_bench, ztrmv_, z_create_matrix, "ztrmv",
112     gemv_bench, dgemv_, d_create_matrix, "dgemv",
113     gemv_bench, zgemv_, z_create_matrix, "zgemv",
114     ger_bench, dger_, d_create_matrix, "dger",
115     ger_bench, zgerc_, z_create_matrix, "zgerc",
116 };
117
118 inline static double delta_time(struct timespec tick) {
119     struct timespec tock;
120         clock_gettime(CLOCK_MONOTONIC, &tock);
121         return (tock.tv_sec - tick.tv_sec) + (tock.tv_nsec - tick.tv_nsec) / 1e9;
122 }
123
124 double pthread_bench(BenchParam * param, int nb_threads)
125 {
126 #ifdef _WIN32
127     return 0;
128 #else
129     BenchParam threaded_param = *param;
130     pthread_t threads[nb_threads];
131     int t, rc;
132     struct timespec tick;
133     threaded_param.n_loop /= nb_threads;
134     clock_gettime(CLOCK_MONOTONIC, &tick);
135     for(t=0; t<nb_threads; t++){
136         rc = pthread_create(&threads[t], NULL, pthread_func_wrapper, &threaded_param);
137         if (rc){
138             printf("ERROR; return code from pthread_create() is %d\n", rc);
139             exit(-1);
140         }
141     }
142     for(t=0; t<nb_threads; t++){
143         pthread_join(threads[t], NULL);
144     }
145         return delta_time(tick);
146 #endif
147 }
148
149 double seq_bench(BenchParam * param) {
150     struct timespec tick;
151     clock_gettime(CLOCK_MONOTONIC, &tick);
152     param->bench_func(param);
153     return delta_time(tick);
154 }
155
156 double omp_bench(BenchParam * param) {
157     BenchParam threaded_param = *param;
158     struct timespec tick;
159     int t;
160     int nb_threads = omp_get_max_threads();
161     threaded_param.n_loop /= nb_threads;
162     clock_gettime(CLOCK_MONOTONIC, &tick);
163     #pragma omp parallel for
164     for(t = 0; t < nb_threads; t ++){
165         param->bench_func(&threaded_param);
166     }
167     return delta_time(tick);
168 }
169
170 int main(int argc, char * argv[]) {
171     double inc_factor = exp(log((double)MAX_SIZE / MIN_SIZE) / NB_SIZE);
172     BenchParam param;
173     int test_id;
174     printf ("Running on %d threads\n", omp_get_max_threads());
175     for(test_id = 0; test_id < NB_TESTS; test_id ++) {
176         double size = MIN_SIZE;
177         param.bench_func = TESTS[test_id * 4];
178         param.blas_func = TESTS[test_id * 4 + 1];
179         param.create_matrix = TESTS[test_id * 4 + 2];
180         printf("\nBenchmark of %s\n", (char*)TESTS[test_id * 4 + 3]);
181         param.n_loop = NLOOP;
182         while(size <= MAX_SIZE) {
183             param.matrix_size = (int)(size + 0.5);
184             double seq_time = seq_bench(&param);
185             double omp_time = omp_bench(&param);
186             double pthread_time = pthread_bench(&param, omp_get_max_threads());
187             printf("matrix size %d, sequential %gs, openmp %gs, speedup %g, "
188                    "pthread %gs, speedup %g\n",
189                    param.matrix_size, seq_time,
190                    omp_time, seq_time / omp_time,
191                    pthread_time, seq_time / pthread_time);
192             size *= inc_factor;
193         }
194     }
195     return(0);
196 }