1/*******************************************************************************
2* Copyright 2021-2022 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 "dnn_types.hpp"
18#include "dnnl_common.hpp"
19
20#include "utils/perf_report.hpp"
21
22void base_perf_report_t::report(res_t *res, const char *prb_str) const {
23 dump_perf_footer();
24
25 std::stringstream ss;
26
27 const char *pt = pt_;
28 char c;
29 while ((c = *pt++) != '\0') {
30 if (c != '%') {
31 ss << c;
32 continue;
33 }
34 handle_option(ss, pt, res, prb_str);
35 }
36
37 std::string str = ss.str();
38 BENCHDNN_PRINT(0, "%s\n", str.c_str());
39};
40
41void base_perf_report_t::dump_engine(std::ostream &s) const {
42 s << engine_tgt_kind;
43}
44
45void base_perf_report_t::handle_option(std::ostream &s, const char *&option,
46 res_t *res, const char *prb_str) const {
47 timer::timer_t::mode_t mode = timer::timer_t::min;
48 (void)mode;
49 double unit = 1e0;
50 char c = *option;
51
52 if (c == '-' || c == '0' || c == '+') {
53 mode = modifier2mode(c);
54 c = *(++option);
55 }
56
57 if (c == 'K' || c == 'M' || c == 'G') {
58 unit = modifier2unit(c);
59 c = *(++option);
60 }
61
62 auto get_flops = [&](const timer::timer_t &t) -> double {
63 if (!t.sec(mode)) return 0;
64 return ops() / t.sec(mode) / unit;
65 };
66
67 auto get_bw = [&](const timer::timer_t &t) -> double {
68 if (!t.sec(mode)) return 0;
69 return (res->ibytes + res->obytes) / t.sec(mode) / unit;
70 };
71
72 auto get_freq = [&](const timer::timer_t &t) -> double {
73 if (!t.sec(mode)) return 0;
74 return t.ticks(mode) / t.sec(mode) / unit;
75 };
76
77 // Please update doc/knobs_perf_report.md in case of any new options!
78
79#define HANDLE(opt, ...) \
80 if (!strncmp(opt "%", option, strlen(opt) + 1)) { \
81 __VA_ARGS__; \
82 option += strlen(opt) + 1; \
83 return; \
84 }
85
86 // Options operating on driver specific types, e.g. alg_t.
87 HANDLE("alg", dump_alg(s));
88 HANDLE("cfg", dump_cfg(s));
89 HANDLE("desc", dump_desc(s));
90 HANDLE("DESC", dump_desc_csv(s));
91 HANDLE("engine", dump_engine(s));
92 HANDLE("flags", dump_flags(s));
93 HANDLE("activation", dump_rnn_activation(s));
94 HANDLE("direction", dump_rnn_direction(s));
95 // Options operating on common types, e.g. attr_t.
96 HANDLE("attr", if (attr() && !attr()->is_def()) s << *attr());
97 HANDLE("axis", if (axis()) s << *axis());
98 HANDLE("dir", if (dir()) s << *dir());
99 HANDLE("dt", if (dt()) s << *dt());
100 HANDLE("group", if (group()) s << *group());
101 HANDLE("sdt", if (sdt()) s << *sdt());
102 HANDLE("stag", if (stag()) s << *stag());
103 HANDLE("mb", if (user_mb()) s << *user_mb());
104 HANDLE("name", if (name()) s << *name());
105 HANDLE("ddt", if (ddt()) s << *ddt());
106 HANDLE("dtag", if (dtag()) s << *dtag());
107 HANDLE("prop", if (prop()) s << prop2str(*prop()));
108 HANDLE("tag", if (tag()) s << *tag());
109 HANDLE("stat_tag", if (stat_tag()) s << *stat_tag());
110 HANDLE("wtag", if (wtag()) s << *wtag());
111 HANDLE("ctx-init", s << *ctx_init());
112 HANDLE("ctx-exe", s << *ctx_exe());
113 // Options operating on driver independent objects, e.g. timer values.
114 HANDLE("bw", s << get_bw(res->timer_map.perf_timer()));
115 HANDLE("driver", s << driver_name);
116 HANDLE("flops", s << get_flops(res->timer_map.perf_timer()));
117 HANDLE("clocks", s << res->timer_map.perf_timer().ticks(mode) / unit);
118 HANDLE("prb", s << prb_str);
119 HANDLE("freq", s << get_freq(res->timer_map.perf_timer()));
120 HANDLE("ops", s << ops() / unit);
121 HANDLE("time", s << res->timer_map.perf_timer().ms(mode) / unit);
122 HANDLE("impl", s << res->impl_name);
123 HANDLE("ibytes", s << res->ibytes / unit);
124 HANDLE("obytes", s << res->obytes / unit);
125 HANDLE("iobytes", s << (res->ibytes + res->obytes) / unit);
126 HANDLE("idx", s << benchdnn_stat.tests);
127
128#undef HANDLE
129
130 auto opt_name = std::string(option);
131 opt_name.pop_back();
132 BENCHDNN_PRINT(0, "Error: perf report option \"%s\" is not supported\n",
133 opt_name.c_str());
134 SAFE_V(FAIL);
135}
136