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