• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
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 #ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
18 #define ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
19 
20 #ifndef NN_COMPATIBILITY_LIBRARY_BUILD
21 #define ATRACE_TAG ATRACE_TAG_NNAPI
22 #include <utils/Trace.h>
23 #endif  // NN_COMPATIBILITY_LIBRARY_BUILD
24 
25 // Neural Networks API (NNAPI) systracing
26 //
27 // Primary goal of the tracing is to capture and present timings for NNAPI.
28 // (Other uses include providing visibility to split of execution between
29 // drivers and the CPU fallback, and the ability to visualize call sequences).
30 //
31 // The tracing has three parts:
32 //  1 Trace macros defined in this file and used throughout the codebase,
33 //    modelled after and using atrace. These implement a naming convention for
34 //    the tracepoints, interpreted by the systrace parser.
35 //  2 Android systrace (atrace) on-device capture and host-based analysis.
36 //  3 A systrace parser (TODO) to summarize the timings.
37 //
38 // For an overview and introduction, please refer to the "NNAPI Systrace design
39 // and HOWTO" (internal Docs for now). This header doesn't try to replicate all
40 // the information in that document. For the contract between traces in code and
41 // the statistics created by the systrace parser, see
42 // tools/systrace-parser/contract-between-code-and-parser.txt.
43 //
44 // Glossary:
45 // - Phase: stage in processing (e.g., Preparation, Compilation, Execution);
46 //   Overall phase nests rest, Execution nests Input/Output, Transformation,
47 //   Computation and Results; optionally Executions can be nested in a
48 //   Warmup and Benchmark - otherwise not nested (Initialization phase
49 //   functions may occur inside other phases but will be counted out during
50 //   analysis). Nested phases (other than Initialization) are analysed as a
51 //   breakdown of the parent phase.
52 // - Layer: component in the stack (from top to bottom: App, Runtime, IPC,
53 //   Driver/CPU). Calls to lower layers are typically nested within calls to upper
54 //   layers.
55 // - Bucket: unit of timing analysis, the combination of Phase and Layer (and
56 //   thus also typically nested).
57 // - Detail: specific unit being executed, typically a function.
58 
59 // Convenience macros to be used in the code (phases defined below).
60 // (Macros so that string concatenation is done at compile time).
61 //
62 // These exist in three variants:
63 // - Simple (NNTRACE_<layer and potentially phase>) - to be used when only one
64 //   Phase is active within a scope
65 // - "Switch" (NNTRACE_<...>_SWITCH) - to be used when multiple Phases
66 //   share a scope (e.g., transformation of data and computation in same
67 //   function).
68 // - "Subtract" (NNTRACE_<...>_SUBTRACT) - to be used when nesting is violated
69 //   and the time should be subtracted from the parent scope
70 // Arguments:
71 // - phase: one of the NNTRACE_PHASE_* macros defined below.
72 // - detail: free-form string constant, typically function name.
73 // Example usage:
74 //   // Simple
75 //   int ANeuralNetworksMemory_createFromFd(...) {
76 //     NNTRACE_RT(NNTRACE_PHASE_PREPARATION, "ANeuralNetworksMemory_createFromFd");
77 //   }
78 //   // Switch
79 //   bool concatenationFloat32(...) {
80 //     NNTRACE_TRANS("concatenationFloat32");  // Transformation of data begins
81 //     ...
82 //     NNTRACE_COMP_SWITCH("optimized_ops::Concatenation"); // Transformation
83 //                                                          // ends and computation
84 //                                                          // begins
85 //   }
86 //   // Subtract
87 //   static int compile(...) {
88 //     NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_COMPILATION, "prepareModel");
89 //     device->getInterface()->prepareModel(..., preparedModelCallback);
90 //     preparedModelCallback->wait()
91 //   }
92 //   ErrorStatus VersionedIDevice::prepareModel(...) {
93 //     ... IPC work ...
94 //     {
95 //       NNTRACE_FULL_SUBTRACT(NNTRACE_LAYER_RUNTIME, NNTRACE_PHASE_COMPILATION,
96 //                             "VersionedIDevice::prepareModel");
97 //       ... Runtime work ...
98 //     }
99 //     ... IPC work ...
100 //   }
101 //
102 // Layer Application - For native applications (e.g., unit tests)
103 #define NNTRACE_APP(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_APPLICATION, phase, detail)
104 #define NNTRACE_APP_SWITCH(phase, detail) \
105     NNTRACE_FULL_SWITCH(NNTRACE_LAYER_APPLICATION, phase, detail)
106 // Layer Runtime - For the NNAPI runtime
107 #define NNTRACE_RT(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_RUNTIME, phase, detail)
108 #define NNTRACE_RT_SWITCH(phase, detail) NNTRACE_FULL_SWITCH(NNTRACE_LAYER_RUNTIME, phase, detail)
109 // Layer CPU - CPU executor
110 #define NNTRACE_CPU(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, phase, detail)
111 #define NNTRACE_COMP(detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, NNTRACE_PHASE_COMPUTATION, detail)
112 #define NNTRACE_COMP_SWITCH(detail) \
113     NNTRACE_FULL_SWITCH(NNTRACE_LAYER_CPU, NNTRACE_PHASE_COMPUTATION, detail)
114 #define NNTRACE_TRANS(detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, NNTRACE_PHASE_TRANSFORMATION, detail)
115 
116 // Fully specified macros to be used when no convenience wrapper exists for your
117 // need.
118 #define NNTRACE_FULL(layer, phase, detail) NNTRACE_NAME_1(("[NN_" layer "_" phase "]" detail))
119 #define NNTRACE_FULL_SWITCH(layer, phase, detail) \
120     NNTRACE_NAME_SWITCH(("[SW][NN_" layer "_" phase "]" detail))
121 #define NNTRACE_FULL_SUBTRACT(layer, phase, detail) \
122     NNTRACE_NAME_1(("[SUB][NN_" layer "_" phase "]" detail))
123 // Raw macro without scoping requirements, for special cases
124 #define NNTRACE_FULL_RAW(layer, phase, detail) \
125     android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, ("[NN_" layer "_" phase "]" detail))
126 
127 // Tracing buckets - for calculating timing summaries over.
128 //
129 // Application-only phases
130 #define NNTRACE_PHASE_OVERALL "PO"     // Overall program, e.g., one benchmark case
131 #define NNTRACE_PHASE_WARMUP "PWU"     // Warmup (nesting multiple executions)
132 #define NNTRACE_PHASE_BENCHMARK "PBM"  // Benchmark (nesting multiple executions)
133 // Main phases, usable by all layers
134 #define NNTRACE_PHASE_INITIALIZATION "PI"  // Initialization - not related to a model
135 #define NNTRACE_PHASE_PREPARATION "PP"     // Model construction
136 #define NNTRACE_PHASE_COMPILATION "PC"     // Model compilation
137 #define NNTRACE_PHASE_EXECUTION "PE"       // Executing the model
138 #define NNTRACE_PHASE_TERMINATION "PT"     // Tearing down
139 #define NNTRACE_PHASE_UNSPECIFIED "PU"     // Helper code called from multiple phases
140 // Subphases of execution
141 #define NNTRACE_PHASE_INPUTS_AND_OUTPUTS "PIO"  // Setting inputs/outputs and allocating buffers
142 #define NNTRACE_PHASE_TRANSFORMATION "PTR"      // Transforming data for computation
143 #define NNTRACE_PHASE_COMPUTATION "PCO"         // Computing operations' outputs
144 #define NNTRACE_PHASE_RESULTS "PR"              // Reading out results
145 // Layers
146 #define NNTRACE_LAYER_APPLICATION "LA"
147 #define NNTRACE_LAYER_RUNTIME "LR"
148 #define NNTRACE_LAYER_IPC "LI"
149 #define NNTRACE_LAYER_DRIVER "LD"
150 #define NNTRACE_LAYER_CPU "LC"
151 #define NNTRACE_LAYER_OTHER "LO"
152 #define NNTRACE_LAYER_UTILITY "LU"  // Code used from multiple layers
153 
154 #ifndef NN_COMPATIBILITY_LIBRARY_BUILD
155 
156 // Implementation
157 //
158 // Almost same as ATRACE_NAME, but enforcing explicit distinction between
159 // phase-per-scope and switching phases.
160 //
161 // Basic trace, one per scope allowed to enforce disjointness
162 #define NNTRACE_NAME_1(name) android::ScopedTrace ___tracer_1(ATRACE_TAG, name)
163 // Switching trace, more than one per scope allowed, translated by
164 // systrace_parser.py. This is mainly useful for tracing multiple phases through
165 // one function / scope.
166 #define NNTRACE_NAME_SWITCH(name)                                      \
167     android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name); \
168     (void)___tracer_1  // ensure switch is only used after a basic trace
169 
170 #else
171 
172 #define NNTRACE_NAME_1(name)       // empty
173 #define NNTRACE_NAME_SWITCH(name)  // empty
174 
175 #endif  // NN_COMPATIBILITY_LIBRARY_BUILD
176 
177 // Disallow use of raw ATRACE macros
178 #undef ATRACE_NAME
179 #undef ATRACE_CALL
180 
181 #endif  // ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
182