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 | |
22 | void 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 | |
41 | void base_perf_report_t::dump_engine(std::ostream &s) const { |
42 | s << engine_tgt_kind; |
43 | } |
44 | |
45 | void 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 | |