1 /*
2
3 Copyright (C) 2008-2016 Michele Martone
4
5 This file is part of librsb.
6
7 librsb is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 librsb is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with librsb; see the file COPYING.
19 If not, see <http://www.gnu.org/licenses/>.
20
21 */
22 /* @cond INNERDOC */
23 /**
24 * @file
25 * @author Michele Martone
26 * @brief Floating point microbenchmarks.
27 */
28
29 #include "rsb_common.h"
30 #include "rsb.h"
31 #include <limits.h>
32
33 #define RSB_DECLARE_FPB_F(FN) rsb_err_t FN(rsb__times_t times, size_t bs, rsb_bool_t aloud) /* times to perform, buffer size */
34 #define RSB_M 1000000.0
35 typedef rsb_err_t (*rsb_fpb_fp_t)(rsb__times_t,size_t,rsb_bool_t); /* floating point benchmark function pointer type */
36
37 #define RSB_DEFINE_FPB_F(FNAME,FPBEXPR,FPBNAME) \
38 static RSB_DECLARE_FPB_F(FNAME) \
39 { \
40 /* \ingroup gr_internals */ \
41 rsb_nnz_idx_t N; rsb__times_t t,T=times; rsb_time_t dt; \
42 rsb_type_t mtca[]=RSB_MATRIX_TYPE_CODES_ARRAY; rsb_char_t*mtcn[]=RSB_MATRIX_TYPES_ARRAY; \
43 rsb_int ti=0; void *p=NULL; \
44 p = rsb__calloc(bs); \
45 if(!p) return RSB_ERR_ENOMEM; \
46 for(ti=0;ti<RSB_IMPLEMENTED_TYPES;++ti) \
47 { \
48 rsb_char_t *tn=mtcn[ti]; rsb_type_t typecode=mtca[ti]; \
49 rsb_aligned_t alpha[RSB_CONST_ENOUGH_ALIGNED_FOR_ANY_TYPE]; \
50 \
51 /* RSB_INFO("bs:%zd, T:%zd\n",bs,T); */ \
52 \
53 N=bs/RSB_SIZEOF(typecode); \
54 rsb__util_set_area_to_converted_integer(&alpha,typecode,1); \
55 rsb__util_set_array_to_converted_integer(p,typecode,N,1,1); \
56 dt = - rsb_time(); \
57 for(t=0;t<T;++t) \
58 FPBEXPR; \
59 dt += rsb_time(); \
60 if(aloud) \
61 RSB_INFO("#op\ttype\tbs\tpasses\telements\tMOPS\n"), \
62 RSB_INFO("%s\t%s\t%zd\t%zd\t%zd\t%f\n",FPBNAME,tn,bs,(size_t)times,(size_t)N,(((1.0/dt)*N)*T)/RSB_M); \
63 } \
64 RSB_CONDITIONAL_FREE(p); \
65 return RSB_ERR_NO_ERROR; \
66 }
67
68 RSB_INTERNALS_COMMON_HEAD_DECLS
69
70 /* This is horrible and sad, sad, I know. */
71 RSB_DEFINE_FPB_F(rsb_fpb_add,rsb__util_vector_add(p,&alpha,typecode,N),"ADD")
72 RSB_DEFINE_FPB_F(rsb_fpb_sum,rsb__util_vector_sum(&alpha,p,typecode,N),"SUM")
73 RSB_DEFINE_FPB_F(rsb_fpb_mul,rsb__cblas_Xscal(typecode,N,&alpha,p,1),"MUL")
74 RSB_DEFINE_FPB_F(rsb_fpb_neg,rsb__util_do_negate(p,typecode,N),"NEG")
75 RSB_DEFINE_FPB_F(rsb_fpb_inc,rsb__vector_increase_by_one(p,typecode,N),"INC")
76 RSB_DEFINE_FPB_F(rsb_fpb_sqr,rsb__util_vector_sqrt(p,typecode,N),"SQR")
77 RSB_DEFINE_FPB_F(rsb_fpb_div,rsb__util_vector_div(p,&alpha,typecode,N),"DIV")
78
rsb__fp_benchmark(void)79 rsb_err_t rsb__fp_benchmark(void)
80 {
81 /**
82 * Will benchmark the floating point units.
83 * You should call rsb_lib_init(RSB_NULL_INIT_OPTIONS) before.
84 *
85 * TODO: pow, log
86 * benchmark for ops in the L1
87 * strided ops
88 *
89 */
90 rsb_fpb_fp_t fpba[]={rsb_fpb_add,rsb_fpb_sum,rsb_fpb_mul,rsb_fpb_neg,rsb_fpb_inc,rsb_fpb_sqr,rsb_fpb_div};
91 rsb_int i;
92 // size_t bs = rsb__get_lastlevel_c_size();
93 // size_t bs = rsb__get_first_level_c_size();
94 rsb_int_t cln = rsb__get_cache_levels_num(),cli;
95 rsb__times_t times,mtimes = RSB_MEMSCAN_MIN_TIMES,Mtimes = RSB_MEMSCAN_MAX_TIMES;
96 rsb_time_t mt = RSB_FPBENCH_MULTITYPE_TIME;
97 rsb_err_t errval = RSB_ERR_NO_ERROR;
98
99 for(cli=1;cli<=cln;++cli)
100 for(i=0;i<sizeof(fpba)/sizeof(rsb_fpb_fp_t);++i)
101 {
102 size_t bs = rsb__get_lnc_size(cli);
103 if(!bs)
104 {
105 errval = RSB_ERR_INTERNAL_ERROR;
106 RSB_PERR_GOTO(err,RSB_ERRM_ES);
107 }
108 RSB_INFO("#probing for an iterations count (to a total of %f s) .. \n",mt);
109 for(times=mtimes;times<Mtimes;times*=2)
110 {
111 rsb_bool_t aloud = RSB_BOOL_FALSE;
112 rsb_time_t dt;
113
114 dt = - rsb_time();
115 fpba[i](times,bs,aloud);
116 dt += rsb_time();
117 if(dt>mt)
118 {
119 aloud = RSB_BOOL_TRUE,
120 fpba[i](times,bs,aloud);
121 break; /* break the inner loop, go for another benchmark */
122 }
123 }
124 }
125 err:
126 RSB_DO_ERR_RETURN(errval)
127 }
128
129 /* @endcond */
130