Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / thirdparty / clDNN / tests / test_utils / instrumentation.cpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16
17 #include "instrumentation.h"
18
19 #include <fstream>
20 #include <iomanip>
21 #include <string>
22 #include <vector>
23 #include <iostream>
24
25
26 namespace instrumentation {
27     // initalize dumping directory for whole run
28     const std::string logger::dump_dir = DUMP_DIRECTORY;
29
30     static float convert_half_to_float(half_t val, bool flush_denorm_to_zero = false)
31     {
32 #if defined HALF_HALF_HPP
33         return val;
34 #else
35         // FP32 parts extracted from FP16.
36         uint32_t sign = (static_cast<uint16_t>(val) & 0x8000U) << 16;
37         uint32_t mantissa = (static_cast<uint16_t>(val) & 0x3FFU) << 13;
38
39         uint32_t exp_val_f16 = (static_cast<uint16_t>(val) & 0x7C00U) >> 10;
40         uint32_t exp;
41         if (exp_val_f16 == 0)
42         {
43             // Handling +/-0 and denormals.
44             if (mantissa == 0)
45             {
46                 exp = 0;
47             }
48             else if (flush_denorm_to_zero)
49             {
50                 sign = 0;
51                 exp = 0;
52                 mantissa = 0;
53             }
54             else
55             {
56                 // Denorms conversion to normal numbers.
57                 exp = 127 - 15;
58                 while (!(mantissa & 0x400000U))
59                 {
60                     mantissa <<= 1;
61                     --exp;
62                 }
63                 mantissa = (mantissa << 1) & 0x7FFFFFU;
64                 exp <<= 23;
65             }
66         }
67         else
68         {
69             // Handling +/-infinity, NaN and normal numbers.
70             exp = (exp_val_f16 == 0x1FU ? 0xFFU : exp_val_f16 + 127 - 15) << 23;
71         }
72
73         float ret;
74         reinterpret_cast<uint32_t&>(ret) = sign | exp | mantissa;
75
76         return ret;
77 #endif
78     }
79
80     float convert_element(float f)
81     {
82         return f;
83     }
84
85     float convert_element(half_t h)
86     {
87         return convert_half_to_float(h);
88     }
89
90     template<typename elemType>
91     void dump_byxf(const cldnn::memory& mem, bool single_batch, cldnn::tensor::value_type batch_id, bool single_feature, cldnn::tensor::value_type feature_id, std::vector<std::vector<std::stringstream>> & streams)
92     {
93         auto mem_arg = mem.get_layout();
94         auto mem_ptr = mem.pointer<elemType>();
95
96         unsigned int input_it = 0;
97         for (cldnn::tensor::value_type b = 0; b < mem_arg.size.batch[0]; b++)
98         {
99             for (cldnn::tensor::value_type y = 0; y < mem_arg.size.spatial[1]; y++)
100             {
101                 for (cldnn::tensor::value_type x = 0; x < mem_arg.size.spatial[0]; x++)
102                 {
103                     for (cldnn::tensor::value_type f = 0; f < mem_arg.size.feature[0]; f++)
104                     {
105                         if ((!single_batch || b == batch_id) && (!single_feature || f == feature_id))
106                         {
107                             streams[b][f] << convert_element(mem_ptr[input_it]) << " ";
108                             if (x == mem_arg.size.spatial[0] - 1)
109                             {
110                                 streams[b][f] << std::endl;
111                             }
112                         }
113                         input_it++;
114                     }
115                 }
116             }
117         }
118     }
119
120     template<typename elemType>
121     void dump_bfyx(const cldnn::memory& mem, bool single_batch, cldnn::tensor::value_type batch_id, bool single_feature, cldnn::tensor::value_type feature_id, std::vector<std::vector<std::stringstream>> & streams)
122     {
123         auto mem_arg = mem.get_layout();
124         auto mem_ptr = mem.pointer<elemType>();
125
126         unsigned int input_it = 0;
127         for (cldnn::tensor::value_type b = 0; b < mem_arg.size.batch[0]; b++)
128         {
129             for (cldnn::tensor::value_type f = 0; f < mem_arg.size.feature[0]; f++)
130             {
131                 for (cldnn::tensor::value_type y = 0; y < mem_arg.size.spatial[1]; y++)
132                 {
133                     for (cldnn::tensor::value_type x = 0; x < mem_arg.size.spatial[0]; x++)
134                     {
135                         if ((!single_batch || b == batch_id) && (!single_feature || f == feature_id))
136                         {
137                             streams[b][f] << convert_element(mem_ptr[input_it]) << " ";
138                             if (x == mem_arg.size.spatial[0] - 1)
139                             {
140                                 streams[b][f] << std::endl;
141                             }
142                         }
143                         input_it++;
144                     }
145                 }
146             }
147         }
148     }
149
150     template<typename elemType>
151     void dump_yxfb(const cldnn::memory& mem, bool single_batch, cldnn::tensor::value_type batch_id, bool single_feature, cldnn::tensor::value_type feature_id, std::vector<std::vector<std::stringstream>> & streams)
152     {
153         auto mem_arg = mem.get_layout();
154         auto mem_ptr = mem.pointer<elemType>();
155
156         unsigned int input_it = 0;
157         for (cldnn::tensor::value_type y = 0; y < mem_arg.size.spatial[1]; y++)
158         {
159             for (cldnn::tensor::value_type x = 0; x < mem_arg.size.spatial[0]; x++)
160             {
161                 for (cldnn::tensor::value_type f = 0; f < mem_arg.size.feature[0]; f++)
162                 {
163                     for (cldnn::tensor::value_type b = 0; b < mem_arg.size.batch[0]; b++)
164                     {
165                         if ((!single_batch || b == batch_id) && (!single_feature || f == feature_id))
166                         {
167                             streams[b][f] << convert_element(mem_ptr[input_it]) << " ";
168                             if (x == mem_arg.size.spatial[0] - 1)
169                             {
170                                 streams[b][f] << std::endl;
171                             }
172                         }
173                         input_it++;
174                     }
175                 }
176             }
177         }
178     }
179
180     template<typename elemType>
181     void dump_xb(const cldnn::memory& mem, bool single_batch, cldnn::tensor::value_type batch_id, std::vector<std::vector<std::stringstream>> & streams)
182     {
183         auto mem_arg = mem.get_layout();
184         auto mem_ptr = mem.pointer<elemType>();
185
186         unsigned int input_it = 0;
187         for (cldnn::tensor::value_type x = 0; x < mem_arg.size.spatial[0]; x++)
188         {
189             for (cldnn::tensor::value_type b = 0; b < mem_arg.size.batch[0]; b++)
190             {
191                 if (!single_batch || b == batch_id)
192                 {
193                     streams[b][0] << convert_element(mem_ptr[input_it]) << std::endl;
194                 }
195                 input_it++;
196             }
197         }
198     }
199
200     template<typename elemType>
201     void dump_bx(const cldnn::memory& mem, bool single_batch, cldnn::tensor::value_type batch_id, std::vector<std::vector<std::stringstream>> & streams)
202     {
203         auto mem_arg = mem.get_layout();
204         auto mem_ptr = mem.pointer<elemType>();
205
206         unsigned int input_it = 0;
207         for (cldnn::tensor::value_type b = 0; b < mem_arg.size.batch[0]; b++)
208         {
209             for (cldnn::tensor::value_type x = 0; x < mem_arg.size.spatial[0]; x++)
210             {
211                 if (!single_batch || b == batch_id)
212                 {
213                     streams[b][0] << convert_element(mem_ptr[input_it]) << std::endl;
214                 }
215                 input_it++;
216             }
217         }
218     }
219
220     template<typename elemType>
221     void dump_yxio(const cldnn::memory& mem, std::stringstream & stream)
222     {
223         auto mem_arg = mem.get_layout();
224         auto mem_ptr = mem.pointer<elemType>();
225
226         auto i_size = mem_arg.size.batch[0];
227         auto o_size = mem_arg.size.feature[0];
228         auto x_size = mem_arg.size.spatial[0];
229         auto y_size = mem_arg.size.spatial[1];
230         unsigned int input_it = 0;
231         for (cldnn::tensor::value_type o = 0; o < o_size; o++)
232         {
233             for (cldnn::tensor::value_type i = 0; i < i_size; i++)
234             {
235                 for (cldnn::tensor::value_type x = 0; x < x_size; x++)
236                 {
237                     for (cldnn::tensor::value_type y = 0; y < y_size; y++)
238                     {
239                         stream<< convert_element(mem_ptr[input_it]) << " ";
240                         input_it++;
241                     }
242                     stream<< std::endl;
243                 }
244             }
245         }
246     }
247
248     template<typename elemType>
249     void dump_oiyx(const cldnn::memory& mem, std::stringstream & stream)
250     {
251         auto mem_arg = mem.get_layout();
252         auto mem_ptr = mem.pointer<elemType>();
253
254         auto i_size = mem_arg.size.batch[0];
255         auto o_size = mem_arg.size.feature[0];
256         auto x_size = mem_arg.size.spatial[0];
257         auto y_size = mem_arg.size.spatial[1];
258         unsigned int input_it = 0;
259         for (cldnn::tensor::value_type x = 0; x < x_size; x++)
260         {
261             for (cldnn::tensor::value_type y = 0; y < y_size; y++)
262             {
263                 for (cldnn::tensor::value_type i = 0; i < i_size; i++)
264                 {
265                     for (cldnn::tensor::value_type o = 0; o < o_size; o++)
266                     {
267                         stream << convert_element(mem_ptr[input_it]) << " ";
268                         input_it++;
269                     }
270                     stream << std::endl;
271                 }
272             }
273         }
274     }
275
276     template<typename elemType>
277     void dump_os_iyx_osv16(const cldnn::memory& mem, std::stringstream & stream)
278     {
279         auto mem_arg = mem.get_layout();
280         auto mem_ptr = mem.pointer<elemType>();
281
282         auto i_size = mem_arg.size.batch[0];
283         auto o_size = mem_arg.size.feature[0];
284         auto x_size = mem_arg.size.spatial[0];
285         auto y_size = mem_arg.size.spatial[1];
286         auto weights_size = i_size * o_size * x_size * y_size; //count() also counts feature[1]
287         int slice_value = 16;
288         cldnn::tensor::value_type it = 0;
289         while (it < weights_size)
290         {
291             stream << convert_element(mem_ptr[it]) << " ";
292             it++;
293             if (it % slice_value == 0) //separate every bsv with a new line
294                 stream << std::endl;
295         };
296     }
297
298     template<typename elemType>
299     void dump_bs_xs_xsv8_bsv8(const cldnn::memory& mem, std::stringstream & stream)
300     {
301         auto mem_arg = mem.get_layout();
302         auto mem_ptr = mem.pointer<elemType>();
303
304         auto i_size = mem_arg.size.batch[0]; //batch = input feature map
305         auto x_size = mem_arg.size.spatial[0]; // spatial_x = output feature map
306         auto weights_size = mem_arg.size.count();
307         int xsv = 8, bsv = 8;
308         unsigned int input_it = 0, input_i_it= 0 , input_o_it = 0;
309         for (cldnn::tensor::value_type it = 0; it < weights_size; it++)
310         {
311                 stream << convert_element(mem_ptr[input_it]) << " ";
312                 input_i_it++;
313                 if (input_i_it % bsv == 0) //separete every input slice with a new line
314                 {
315                     stream << std::endl;
316                     input_o_it++;
317                     input_i_it = 0;
318                 }
319                 input_it = input_o_it*bsv + input_i_it;
320
321                 if (input_it % (xsv*bsv) == 0) // seperate every block (8x8) with a new line
322                     stream << std::endl;
323         }
324     }
325
326     template<typename elemType>
327     void dump_bs_x_bsv16(const cldnn::memory& mem, std::stringstream & stream)
328     {
329         auto mem_arg = mem.get_layout();
330         auto mem_ptr = mem.pointer<elemType>();
331
332         auto i_size = mem_arg.size.batch[0]; //batch = input feature map
333         auto x_size = mem_arg.size.spatial[0]; // spatial_x = output feature map
334         auto weights_size = mem_arg.size.count();
335         int bsv = 16;
336         cldnn::tensor::value_type it = 0;
337         while (it < weights_size)
338         {
339             stream << convert_element(mem_ptr[it]) << " ";
340             it++;
341             if (it % bsv == 0) //separate every bsv with a new line
342                 stream << std::endl;
343         }
344     }
345
346     template <class T>
347     void dump(const cldnn::memory& mem, std::stringstream& stream)
348     {
349         auto mem_ptr = mem.pointer<T>();
350
351         auto&& pitches = mem.get_layout().get_pitches();
352         auto&& size = mem.get_layout().size;
353         for (cldnn::tensor::value_type b = 0; b < size.batch[0]; ++b)
354         {
355             stream << "============= BATCH " << b << " ============\n\n";
356             for (cldnn::tensor::value_type f = 0; f < size.feature[0]; ++f)
357             {
358                 stream << "feature " << f << ":\n";
359                 for (cldnn::tensor::value_type y = 0; y < size.spatial[1]; ++y)
360                 {
361                     for (cldnn::tensor::value_type x = 0; x < size.spatial[0]; ++x)
362                     {
363                         unsigned int input_it = b*pitches.batch[0] + f*pitches.feature[0] + y*pitches.spatial[1] + x*pitches.spatial[0];
364                         stream << convert_element(mem_ptr[input_it]) << " ";
365                         input_it++;
366                     }
367                     stream << '\n';
368                 }
369                 stream << std::endl;
370             }
371         }
372     }
373
374     template <class T>
375     void dump(const cldnn::memory& mem, std::vector<std::vector<std::string>>& dump_strings)
376     {
377         auto mem_ptr = mem.pointer<T>();
378         std::stringstream stream;
379
380         auto&& pitches = mem.get_layout().get_pitches();
381         auto&& size = mem.get_layout().size;
382         for (cldnn::tensor::value_type b = 0; b < size.batch[0]; ++b)
383         {
384             for (cldnn::tensor::value_type f = 0; f < size.feature[0]; ++f)
385             {
386                 for (cldnn::tensor::value_type y = 0; y < size.spatial[1]; ++y)
387                 {
388                     for (cldnn::tensor::value_type x = 0; x < size.spatial[0]; ++x)
389                     {
390                         unsigned int input_it = b*pitches.batch[0] + f*pitches.feature[0] + y*pitches.spatial[1] + x*pitches.spatial[0];
391                         stream << convert_element(mem_ptr[input_it]) << " ";
392                         input_it++;
393                     }
394                     stream << std::endl;
395                     dump_strings[b][f] = stream.str();
396                 }
397             }
398         }
399     }
400
401     void logger::log_memory_to_file(const cldnn::memory& mem, std::string prefix, bool single_batch, cldnn::tensor::value_type batch_id, bool single_feature, cldnn::tensor::value_type feature_id)
402     {
403         auto batch = mem.get_layout().size.batch[0];
404         auto feature = mem.get_layout().size.feature[0];
405         auto eng_type =  "gpu" ;
406         std::vector<std::vector<std::string>> dump_strings(batch);
407         for(cldnn::tensor::value_type b = 0; b < batch; b++)
408         {
409             dump_strings[b].resize(feature);
410         }
411
412         if (mem.get_layout().data_type == cldnn::data_types::f32)
413             dump<float>(mem, dump_strings);
414         else
415             dump<half_t>(mem, dump_strings);
416
417         for (cldnn::tensor::value_type b = 0; b < batch; b++)
418             for (cldnn::tensor::value_type f = 0; f < feature; f++)
419             {
420                 if (!single_batch || (b == batch_id && f == feature_id))
421                 {
422                     std::string filename((dump_dir + "/" + prefix + "_" + eng_type + "_b" + std::to_string(b) + "_f" + std::to_string(f) + ".txt"));
423                     std::ofstream file_stream(filename);
424                     file_stream << dump_strings[b][f];
425                     file_stream.close();
426                 }
427             }
428     }
429
430     void logger::log_weights_to_file(const cldnn::memory& mem, std::string prefix)
431     {
432         std::stringstream stream;
433
434         if (mem.get_layout().data_type == cldnn::data_types::f32)
435             dump<float>(mem, stream);
436         else
437             dump<half_t>(mem, stream);
438
439         std::string filename((dump_dir + "/" + prefix + ".txt"));
440         std::ofstream file_stream(filename);
441         file_stream << stream.str();
442         file_stream.close();
443     }
444 }