c0767c28014033435692b86a5e36d903543c6c8c
[platform/upstream/dldt.git] / inference-engine / src / cldnn_engine / debug_options.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include <iostream>
6 #include <iomanip>
7 #ifndef NDEBUG
8     #include <algorithm>
9     #include <cmath>
10 #endif
11
12 #include "debug_options.h"
13
14 namespace CLDNNPlugin {
15
16 DebugOptions::DebugOptions() {
17     m_bDebugLayerContent =
18 #ifdef _DEBUG_LAYER_CONTENT
19         true;
20 #else
21         false;
22 #endif
23
24     m_bDebugLayerContentIndexed =
25 #ifdef _DEBUG_LAYER_CONTENT_INDEXED
26         true;
27 #else
28         false;
29 #endif
30
31     m_bDebugLayerFormat =
32 #ifdef _DEBUG_LAYER_FORMAT
33         true;
34 #else
35         false;
36 #endif
37
38     m_bPluginPerfPrints =
39 #ifdef _PLUGIN_PERF_PRINTS
40         true;
41 #else
42         false;
43 #endif
44
45     m_maxPrintSize =
46 #ifdef _DEBUG_LAYER_CONTENT_FULL
47         1000000000;
48 #else
49         3;
50 #endif
51 }
52
53 void DebugOptions::PrintOptions() const {
54 #ifndef NDEBUG
55     std::cout << "Debug Options:" << std::endl;
56     std::cout << "\tDebug Layer Content: " << m_bDebugLayerContent << std::endl;
57     std::cout << "\tDebug Layer Content Indexed: " << m_bDebugLayerContentIndexed << std::endl;
58     std::cout << "\tDebug Layers Format: " << m_bDebugLayerFormat << std::endl;
59     std::cout << "\tPlugin Performance Prints: " << m_bPluginPerfPrints << std::endl;
60     std::cout << "\tPrint Size: " << m_maxPrintSize << std::endl;
61 #endif  // NDEBUG
62 }
63
64 std::string DebugOptions::GetFormatName(cldnn::format::type format) {
65     switch (format) {
66     case cldnn::format::yxfb:
67         return "yxfb";
68     case cldnn::format::byxf:
69         return "byxf";
70     case cldnn::format::bfyx:
71         return "bfyx";
72     case cldnn::format::fyxb:
73         return "fyxb";
74     default:
75         return "Unknown Format";
76     }
77 }
78
79 std::string DebugOptions::GetDataTypeName(cldnn::data_types dataType) {
80     switch (dataType) {
81     case cldnn::data_types::f16:
82         return "f16";
83     case cldnn::data_types::f32:
84         return "f32";
85     default:
86         return "Unknown Data Type";
87     }
88 }
89
90 void DebugOptions::PrintInput(const InferenceEngine::TBlob<float>& input) const {
91 #ifndef NDEBUG
92     const float* inputBlobPtr = input.readOnly();
93
94     if (m_bDebugLayerContent) {
95         std::cout << "Input (" << input.size() << ") = ";
96         for (size_t i = 0; i < std::min<size_t>(m_maxPrintSize, input.size()); i++) {
97             std::cout << inputBlobPtr[i] << ", ";
98         }
99         std::cout << std::endl;
100     }
101 #endif  // NDEBUG
102 }
103
104 float DebugOptions::SimpleConvertFP16toFP32(uint16_t u16val) {
105 #ifndef NDEBUG
106     // convert to fp32 (1,5,10)->(1,8,23)
107     // trivial conversion not handling inf/denorm
108     uint32_t sign = (u16val & 0x8000U) << 16;
109     uint32_t mantissa = (u16val & 0x3FFU) << 13;
110     uint32_t exp_val_f16 = (u16val & 0x7C00U) >> 10;
111     uint32_t exp = (exp_val_f16 == 0x1FU ? 0xFFU : exp_val_f16 + 127 - 15) << 23;;
112     uint32_t val = sign | exp | mantissa;
113     float fval = *(reinterpret_cast<float*>(&val));
114     return (fabs(fval) < 1e-4f) ? 0.0f : fval;  // clamp epsilon fp16 to 0
115 #endif  // NDEBUG
116     return 0;
117 }
118 void DebugOptions::PrintIndexedValue(const cldnn::memory& mem, const cldnn::tensor index) const {
119 #ifndef NDEBUG
120     auto layout = mem.get_layout();
121     float fval;
122     switch (layout.data_type) {
123     case cldnn::data_types::f32: {
124         auto p32 = mem.pointer<float>();
125         auto resPtrF32 = p32.data();
126         fval = resPtrF32[CalcLinearIndex(layout, index)];
127     }
128     break;
129     case cldnn::data_types::f16:
130     {
131         auto p16 = mem.pointer<uint16_t>();
132         auto resPtrU16 = p16.data();
133         fval = SimpleConvertFP16toFP32(resPtrU16[CalcLinearIndex(layout, index)]);
134     }
135     break;
136     default:
137         assert(0);  // unhandled data type
138         fval = 0.0f;
139     }
140
141     if (m_bDebugLayerContentIndexed) {
142         std::cout << "\t[";
143         for (size_t i = 0; i < index.raw.size(); i++) {
144             std::cout << index.raw[i] << ",";
145         }
146         std::cout << "] = " << fval << "\n";
147     } else {
148         std::cout << fval << ", ";
149     }
150 #endif  // NDEBUG
151 }
152
153 uint32_t DebugOptions::CalcLinearIndex(const cldnn::layout& memLayout, const cldnn::tensor index) {
154 #ifndef NDEBUG
155     uint32_t bPitch, fPitch, xPitch, yPitch;
156     switch (memLayout.format) {
157     case cldnn::format::yxfb:
158         bPitch = 1;
159         fPitch = memLayout.size.batch[0] * bPitch;
160         xPitch = memLayout.size.feature[0] * fPitch;
161         yPitch = memLayout.size.spatial[1] * xPitch;
162         return (index.batch[0] * bPitch)
163             + (index.feature[0] * fPitch)
164             + (index.spatial[1] * xPitch)
165             + (index.spatial[0] * yPitch);
166         break;
167     case cldnn::format::bfyx:
168         xPitch = 1;
169         yPitch = memLayout.size.spatial[1] * xPitch;
170         fPitch = memLayout.size.spatial[0] * yPitch;
171         bPitch = memLayout.size.feature[0] * fPitch;
172         return (index.batch[0] * bPitch)
173             + (index.feature[0] * fPitch)
174             + (index.spatial[1] * xPitch)
175             + (index.spatial[0] * yPitch);
176         break;
177     default:
178         assert(0);
179         return 0;
180     }
181 #endif  // NDEBUG
182     return 0;
183 }
184
185 void DebugOptions::PrintNetworkOutputs(std::map<cldnn::primitive_id, cldnn::network_output>& outputsMap) const {
186 #ifndef NDEBUG
187     if (!m_bDebugLayerContent && !m_bDebugLayerFormat) {
188         return;
189     }
190
191     for (auto& layer : outputsMap) {
192         std::cout << layer.first << ":\n";
193         auto mem = layer.second.get_memory();
194         auto layout = mem.get_layout();
195         if (m_bDebugLayerFormat) {
196             std::string formatName = GetFormatName(layout.format);
197             std::string datatypeName = GetDataTypeName(layout.data_type);
198             std::cout << "  Layout: ( " <<
199                 GetDataTypeName(layout.data_type) << ", " <<
200                 GetFormatName(layout.format) << ", [";
201             for (auto s : layout.size.sizes()) {
202                 std::cout << s << ",";
203             }
204             std::cout << "] )\n";
205         }
206         if (m_bDebugLayerContent) {
207             DumpSingleOutput(layer.first, outputsMap);
208             std::cout << "\n";
209         }
210     }
211 #endif  // NDEBUG
212 }
213
214 void DebugOptions::DumpSingleOutput(cldnn::primitive_id name, std::map<cldnn::primitive_id, cldnn::network_output>& outputs, bool bSingleFeatureMap) const {
215 #ifndef NDEBUG
216     if (outputs.find(name) == outputs.end()) {
217         std::cout << "Couldn't find output: " << name << std::endl;
218         return;
219     }
220
221     auto output = outputs.at(name);
222     std::cout << name << ":\n";
223     auto mem = output.get_memory();
224     auto layout = mem.get_layout();
225     cldnn::tensor lowerPad = layout.data_padding.lower_size();
226     cldnn::tensor upperPad = layout.data_padding.upper_size();
227     {   // format
228         std::string formatName = GetFormatName(layout.format);
229         std::string datatypeName = GetDataTypeName(layout.data_type);
230         std::cout << "  Layout: ( " <<
231             GetDataTypeName(layout.data_type) << ", " <<
232             GetFormatName(layout.format) << ", [";
233         for (auto s : layout.size.sizes()) {
234             std::cout << s << ",";
235         }
236         std::cout << "] [";
237         for (auto p : layout.data_padding.lower_size().sizes()) {
238             std::cout << p << ",";
239         }
240         std::cout << "] [";
241         for (auto p : layout.data_padding.upper_size().sizes()) {
242             std::cout << p << ",";
243         }
244         std::cout << "] )\n";
245     }
246     {   // content
247         switch (layout.format) {
248         case cldnn::format::bfyx:
249         {
250             std::vector<size_t> pitches;
251             size_t elements = 1;
252             if (bSingleFeatureMap) {
253                 elements = layout.size.spatial[1] * layout.size.spatial[0];
254             } else {
255                 for (int i = 0; i < 4; i++) {
256                     elements *= layout.size.sizes()[i] + lowerPad.sizes()[i] + upperPad.sizes()[i];
257                 }
258             }
259             pitches.push_back(layout.size.spatial[0] + lowerPad.spatial[0] + upperPad.spatial[0]);  // x or width - rowpitch
260             pitches.push_back(pitches[0] * (layout.size.spatial[1] + lowerPad.spatial[1] + upperPad.spatial[1]));  // slice pitch
261             pitches.push_back(pitches[0] * pitches[1] * layout.size.feature[0]);  // depth/feature pitch
262             if (layout.data_type == cldnn::data_types::f32)
263                 DumpElementsRaw<float>(mem, pitches, elements);
264             else
265                 DumpElementsRaw<uint16_t>(mem, pitches, elements);
266             break;
267         }
268         default:
269             assert(0);  // unhandled format
270             return;
271         }
272         std::cout << "\n";
273     }
274 #endif  // NDEBUG
275 }
276
277 void DebugOptions::AddTimedEvent(std::string eventName, std::string startingAt) {
278 #ifdef _PLUGIN_PERF_PRINTS
279     m_TimedEventTimestamp[eventName] = std::chrono::steady_clock::now();
280     if (startingAt.compare(std::string()) == 0) {
281         startingAt = eventName;
282     }
283     m_TimedEventStart[eventName] = startingAt;
284 #endif  // _PLUGIN_PERF_PRINTS
285 }
286
287 void DebugOptions::PrintTimedEvents() {
288 #ifdef _PLUGIN_PERF_PRINTS
289     for (auto& e : m_TimedEventStart) {
290         if (e.first.compare(e.second)) {
291             std::cout << "[Plugin Internal Metric]: \t" << e.first << " took: " <<
292                 std::chrono::duration_cast<std::chrono::duration<double, std::chrono::milliseconds::period>>
293                 (m_TimedEventTimestamp[e.first] - m_TimedEventTimestamp[e.second]).count() << " ms\n";
294         }
295     }
296 #endif  // _PLUGIN_PERF_PRINTS
297 }
298
299 void DebugOptions::ClearTimedEvents() {
300 #ifdef _PLUGIN_PERF_PRINTS
301     m_TimedEventStart.clear();
302     m_TimedEventTimestamp.clear();
303 #endif  // _PLUGIN_PERF_PRINTS
304 }
305
306 void DebugOptions::EnableWA(std::string name) {
307 #ifndef NDEBUG
308     m_workaroundNames.insert(name);
309 #endif  // NDEBUG
310 }
311
312 void DebugOptions::DisableWA(std::string name) {
313 #ifndef NDEBUG
314     m_workaroundNames.erase(name);
315 #endif  // NDEBUG
316 }
317
318 bool DebugOptions::IsWAActive(std::string name) {
319 #ifndef NDEBUG
320     return (m_workaroundNames.find(name) != m_workaroundNames.end());
321 #else
322     return false;
323 #endif  // NDEBUG
324 }
325
326 std::string DebugOptions::IELayoutToString(InferenceEngine::Layout layout) {
327     switch (layout) {
328     case InferenceEngine::ANY: return "ANY";
329     case InferenceEngine::NCHW: return "NCHW";
330     case InferenceEngine::NHWC: return "NHWC";
331     case InferenceEngine::NCDHW: return "NCDHW";
332     case InferenceEngine::OIHW: return "OIHW";
333     case InferenceEngine::C: return "C";
334     case InferenceEngine::CHW: return "CHW";
335     case InferenceEngine::HW: return "HW";
336     case InferenceEngine::NC: return "NC";
337     default: return "Unknown";
338     }
339 }
340
341 };  // namespace CLDNNPlugin