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