1 /*
2
3 BLIS
4 An object-based framework for developing high-performance BLAS-like
5 libraries.
6
7 Copyright (C) 2014, The University of Texas at Austin
8 Copyright (C) 2018 - 2019, Advanced Micro Devices, Inc.
9
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are
12 met:
13 - Redistributions of source code must retain the above copyright
14 notice, this list of conditions and the following disclaimer.
15 - Redistributions in binary form must reproduce the above copyright
16 notice, this list of conditions and the following disclaimer in the
17 documentation and/or other materials provided with the distribution.
18 - Neither the name(s) of the copyright holder(s) nor the names of its
19 contributors may be used to endorse or promote products derived
20 from this software without specific prior written permission.
21
22 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34 */
35
36 #include "blis.h"
37 #include "test_libblis.h"
38
39
40 // Static variables.
41 static char* op_str = "dotv";
42 static char* o_types = "vv"; // x y
43 static char* p_types = "cc"; // conjx conjy
44 static thresh_t thresh[BLIS_NUM_FP_TYPES] = { { 1e-04, 1e-05 }, // warn, pass for s
45 { 1e-04, 1e-05 }, // warn, pass for c
46 { 1e-13, 1e-14 }, // warn, pass for d
47 { 1e-13, 1e-14 } }; // warn, pass for z
48
49 // Local prototypes.
50 void libblis_test_dotv_deps
51 (
52 thread_data_t* tdata,
53 test_params_t* params,
54 test_op_t* op
55 );
56
57 void libblis_test_dotv_experiment
58 (
59 test_params_t* params,
60 test_op_t* op,
61 iface_t iface,
62 char* dc_str,
63 char* pc_str,
64 char* sc_str,
65 unsigned int p_cur,
66 double* perf,
67 double* resid
68 );
69
70 void libblis_test_dotv_impl
71 (
72 iface_t iface,
73 obj_t* x,
74 obj_t* y,
75 obj_t* rho
76 );
77
78 void libblis_test_dotv_check
79 (
80 test_params_t* params,
81 obj_t* x,
82 obj_t* y,
83 obj_t* rho,
84 double* resid
85 );
86
87
88
libblis_test_dotv_deps(thread_data_t * tdata,test_params_t * params,test_op_t * op)89 void libblis_test_dotv_deps
90 (
91 thread_data_t* tdata,
92 test_params_t* params,
93 test_op_t* op
94 )
95 {
96 libblis_test_randv( tdata, params, &(op->ops->randv) );
97 libblis_test_normfv( tdata, params, &(op->ops->normfv) );
98 libblis_test_copyv( tdata, params, &(op->ops->copyv) );
99 }
100
101
102
libblis_test_dotv(thread_data_t * tdata,test_params_t * params,test_op_t * op)103 void libblis_test_dotv
104 (
105 thread_data_t* tdata,
106 test_params_t* params,
107 test_op_t* op
108 )
109 {
110
111 // Return early if this test has already been done.
112 if ( libblis_test_op_is_done( op ) ) return;
113
114 // Return early if operation is disabled.
115 if ( libblis_test_op_is_disabled( op ) ||
116 libblis_test_l1v_is_disabled( op ) ) return;
117
118 // Call dependencies first.
119 if ( TRUE ) libblis_test_dotv_deps( tdata, params, op );
120
121 // Execute the test driver for each implementation requested.
122 //if ( op->front_seq == ENABLE )
123 {
124 libblis_test_op_driver( tdata,
125 params,
126 op,
127 BLIS_TEST_SEQ_FRONT_END,
128 op_str,
129 p_types,
130 o_types,
131 thresh,
132 libblis_test_dotv_experiment );
133 }
134 }
135
136
137
libblis_test_dotv_experiment(test_params_t * params,test_op_t * op,iface_t iface,char * dc_str,char * pc_str,char * sc_str,unsigned int p_cur,double * perf,double * resid)138 void libblis_test_dotv_experiment
139 (
140 test_params_t* params,
141 test_op_t* op,
142 iface_t iface,
143 char* dc_str,
144 char* pc_str,
145 char* sc_str,
146 unsigned int p_cur,
147 double* perf,
148 double* resid
149 )
150 {
151 unsigned int n_repeats = params->n_repeats;
152 unsigned int i;
153
154 double time_min = DBL_MAX;
155 double time;
156
157 num_t datatype;
158
159 dim_t m;
160
161 conj_t conjx, conjy, conjconjxy;
162
163 obj_t x, y, rho;
164
165
166 // Use the datatype of the first char in the datatype combination string.
167 bli_param_map_char_to_blis_dt( dc_str[0], &datatype );
168
169 // Map the dimension specifier to an actual dimension.
170 m = libblis_test_get_dim_from_prob_size( op->dim_spec[0], p_cur );
171
172 // Map parameter characters to BLIS constants.
173 bli_param_map_char_to_blis_conj( pc_str[0], &conjx );
174 bli_param_map_char_to_blis_conj( pc_str[1], &conjy );
175
176 // Create test scalars.
177 bli_obj_scalar_init_detached( datatype, &rho );
178
179 // Create test operands (vectors and/or matrices).
180 libblis_test_vobj_create( params, datatype, sc_str[0], m, &x );
181 libblis_test_vobj_create( params, datatype, sc_str[1], m, &y );
182
183 // Randomize x.
184 libblis_test_vobj_randomize( params, TRUE, &x );
185
186 // Determine whether to make a copy of x with or without conjugation.
187 //
188 // conjx conjy ~conjx^conjy y is initialized as
189 // n n c y = conj(x)
190 // n c n y = x
191 // c n n y = x
192 // c c c y = conj(x)
193 //
194 conjconjxy = bli_apply_conj( conjx, conjy );
195 conjconjxy = bli_conj_toggled( conjconjxy );
196 bli_obj_set_conj( conjconjxy, &x );
197 bli_copyv( &x, &y );
198
199 // Apply the parameters.
200 bli_obj_set_conj( conjx, &x );
201 bli_obj_set_conj( conjy, &y );
202
203 // Repeat the experiment n_repeats times and record results.
204 for ( i = 0; i < n_repeats; ++i )
205 {
206 bli_copysc( &BLIS_MINUS_ONE, &rho );
207
208 time = bli_clock();
209
210 libblis_test_dotv_impl( iface, &x, &y, &rho );
211
212 time_min = bli_clock_min_diff( time_min, time );
213 }
214
215 // Estimate the performance of the best experiment repeat.
216 *perf = ( 2.0 * m ) / time_min / FLOPS_PER_UNIT_PERF;
217 if ( bli_obj_is_complex( &y ) ) *perf *= 4.0;
218
219 // Perform checks.
220 libblis_test_dotv_check( params, &x, &y, &rho, resid );
221
222 // Zero out performance and residual if output scalar is empty.
223 libblis_test_check_empty_problem( &rho, perf, resid );
224
225 // Free the test objects.
226 bli_obj_free( &x );
227 bli_obj_free( &y );
228 }
229
230
231
libblis_test_dotv_impl(iface_t iface,obj_t * x,obj_t * y,obj_t * rho)232 void libblis_test_dotv_impl
233 (
234 iface_t iface,
235 obj_t* x,
236 obj_t* y,
237 obj_t* rho
238 )
239 {
240 switch ( iface )
241 {
242 case BLIS_TEST_SEQ_FRONT_END:
243 bli_dotv( x, y, rho );
244 break;
245
246 default:
247 libblis_test_printf_error( "Invalid interface type.\n" );
248 }
249 }
250
251
252
libblis_test_dotv_check(test_params_t * params,obj_t * x,obj_t * y,obj_t * rho,double * resid)253 void libblis_test_dotv_check
254 (
255 test_params_t* params,
256 obj_t* x,
257 obj_t* y,
258 obj_t* rho,
259 double* resid
260 )
261 {
262 num_t dt_real = bli_obj_dt_proj_to_real( y );
263
264 obj_t rho_r, rho_i;
265 obj_t norm_x, norm_xy;
266
267 double zero;
268 double junk;
269
270 //
271 // Pre-conditions:
272 // - x is randomized.
273 // - y is equal to conj(conjx(conjy(x))).
274 //
275 // Under these conditions, we assume that the implementation for
276 //
277 // rho := conjx(x^T) conjy(y)
278 //
279 // is functioning correctly if
280 //
281 // sqrtsc( rho.real ) - normfv( x )
282 //
283 // and
284 //
285 // rho.imag
286 //
287 // are negligible.
288 //
289
290 bli_obj_scalar_init_detached( dt_real, &rho_r );
291 bli_obj_scalar_init_detached( dt_real, &rho_i );
292 bli_obj_scalar_init_detached( dt_real, &norm_x );
293 bli_obj_scalar_init_detached( dt_real, &norm_xy );
294
295 bli_normfv( x, &norm_x );
296
297 bli_unzipsc( rho, &rho_r, &rho_i );
298
299 bli_sqrtsc( &rho_r, &norm_xy );
300
301 bli_subsc( &norm_x, &norm_xy );
302 bli_getsc( &norm_xy, resid, &junk );
303 bli_getsc( &rho_i, &zero, &junk );
304
305 *resid = bli_fmaxabs( *resid, zero );
306 }
307
308