You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
8.3 KiB
182 lines
8.3 KiB
/*
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
|
|
#define ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
|
|
|
|
#ifndef NN_COMPATIBILITY_LIBRARY_BUILD
|
|
#define ATRACE_TAG ATRACE_TAG_NNAPI
|
|
#include <utils/Trace.h>
|
|
#endif // NN_COMPATIBILITY_LIBRARY_BUILD
|
|
|
|
// Neural Networks API (NNAPI) systracing
|
|
//
|
|
// Primary goal of the tracing is to capture and present timings for NNAPI.
|
|
// (Other uses include providing visibility to split of execution between
|
|
// drivers and the CPU fallback, and the ability to visualize call sequences).
|
|
//
|
|
// The tracing has three parts:
|
|
// 1 Trace macros defined in this file and used throughout the codebase,
|
|
// modelled after and using atrace. These implement a naming convention for
|
|
// the tracepoints, interpreted by the systrace parser.
|
|
// 2 Android systrace (atrace) on-device capture and host-based analysis.
|
|
// 3 A systrace parser (TODO) to summarize the timings.
|
|
//
|
|
// For an overview and introduction, please refer to the "NNAPI Systrace design
|
|
// and HOWTO" (internal Docs for now). This header doesn't try to replicate all
|
|
// the information in that document. For the contract between traces in code and
|
|
// the statistics created by the systrace parser, see
|
|
// tools/systrace-parser/contract-between-code-and-parser.txt.
|
|
//
|
|
// Glossary:
|
|
// - Phase: stage in processing (e.g., Preparation, Compilation, Execution);
|
|
// Overall phase nests rest, Execution nests Input/Output, Transformation,
|
|
// Computation and Results; optionally Executions can be nested in a
|
|
// Warmup and Benchmark - otherwise not nested (Initialization phase
|
|
// functions may occur inside other phases but will be counted out during
|
|
// analysis). Nested phases (other than Initialization) are analysed as a
|
|
// breakdown of the parent phase.
|
|
// - Layer: component in the stack (from top to bottom: App, Runtime, IPC,
|
|
// Driver/CPU). Calls to lower layers are typically nested within calls to upper
|
|
// layers.
|
|
// - Bucket: unit of timing analysis, the combination of Phase and Layer (and
|
|
// thus also typically nested).
|
|
// - Detail: specific unit being executed, typically a function.
|
|
|
|
// Convenience macros to be used in the code (phases defined below).
|
|
// (Macros so that string concatenation is done at compile time).
|
|
//
|
|
// These exist in three variants:
|
|
// - Simple (NNTRACE_<layer and potentially phase>) - to be used when only one
|
|
// Phase is active within a scope
|
|
// - "Switch" (NNTRACE_<...>_SWITCH) - to be used when multiple Phases
|
|
// share a scope (e.g., transformation of data and computation in same
|
|
// function).
|
|
// - "Subtract" (NNTRACE_<...>_SUBTRACT) - to be used when nesting is violated
|
|
// and the time should be subtracted from the parent scope
|
|
// Arguments:
|
|
// - phase: one of the NNTRACE_PHASE_* macros defined below.
|
|
// - detail: free-form string constant, typically function name.
|
|
// Example usage:
|
|
// // Simple
|
|
// int ANeuralNetworksMemory_createFromFd(...) {
|
|
// NNTRACE_RT(NNTRACE_PHASE_PREPARATION, "ANeuralNetworksMemory_createFromFd");
|
|
// }
|
|
// // Switch
|
|
// bool concatenationFloat32(...) {
|
|
// NNTRACE_TRANS("concatenationFloat32"); // Transformation of data begins
|
|
// ...
|
|
// NNTRACE_COMP_SWITCH("optimized_ops::Concatenation"); // Transformation
|
|
// // ends and computation
|
|
// // begins
|
|
// }
|
|
// // Subtract
|
|
// static int compile(...) {
|
|
// NNTRACE_FULL(NNTRACE_LAYER_IPC, NNTRACE_PHASE_COMPILATION, "prepareModel");
|
|
// device->getInterface()->prepareModel(..., preparedModelCallback);
|
|
// preparedModelCallback->wait()
|
|
// }
|
|
// ErrorStatus VersionedIDevice::prepareModel(...) {
|
|
// ... IPC work ...
|
|
// {
|
|
// NNTRACE_FULL_SUBTRACT(NNTRACE_LAYER_RUNTIME, NNTRACE_PHASE_COMPILATION,
|
|
// "VersionedIDevice::prepareModel");
|
|
// ... Runtime work ...
|
|
// }
|
|
// ... IPC work ...
|
|
// }
|
|
//
|
|
// Layer Application - For native applications (e.g., unit tests)
|
|
#define NNTRACE_APP(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_APPLICATION, phase, detail)
|
|
#define NNTRACE_APP_SWITCH(phase, detail) \
|
|
NNTRACE_FULL_SWITCH(NNTRACE_LAYER_APPLICATION, phase, detail)
|
|
// Layer Runtime - For the NNAPI runtime
|
|
#define NNTRACE_RT(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_RUNTIME, phase, detail)
|
|
#define NNTRACE_RT_SWITCH(phase, detail) NNTRACE_FULL_SWITCH(NNTRACE_LAYER_RUNTIME, phase, detail)
|
|
// Layer CPU - CPU executor
|
|
#define NNTRACE_CPU(phase, detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, phase, detail)
|
|
#define NNTRACE_COMP(detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, NNTRACE_PHASE_COMPUTATION, detail)
|
|
#define NNTRACE_COMP_SWITCH(detail) \
|
|
NNTRACE_FULL_SWITCH(NNTRACE_LAYER_CPU, NNTRACE_PHASE_COMPUTATION, detail)
|
|
#define NNTRACE_TRANS(detail) NNTRACE_FULL(NNTRACE_LAYER_CPU, NNTRACE_PHASE_TRANSFORMATION, detail)
|
|
|
|
// Fully specified macros to be used when no convenience wrapper exists for your
|
|
// need.
|
|
#define NNTRACE_FULL(layer, phase, detail) NNTRACE_NAME_1(("[NN_" layer "_" phase "]" detail))
|
|
#define NNTRACE_FULL_SWITCH(layer, phase, detail) \
|
|
NNTRACE_NAME_SWITCH(("[SW][NN_" layer "_" phase "]" detail))
|
|
#define NNTRACE_FULL_SUBTRACT(layer, phase, detail) \
|
|
NNTRACE_NAME_1(("[SUB][NN_" layer "_" phase "]" detail))
|
|
// Raw macro without scoping requirements, for special cases
|
|
#define NNTRACE_FULL_RAW(layer, phase, detail) \
|
|
android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, ("[NN_" layer "_" phase "]" detail))
|
|
|
|
// Tracing buckets - for calculating timing summaries over.
|
|
//
|
|
// Application-only phases
|
|
#define NNTRACE_PHASE_OVERALL "PO" // Overall program, e.g., one benchmark case
|
|
#define NNTRACE_PHASE_WARMUP "PWU" // Warmup (nesting multiple executions)
|
|
#define NNTRACE_PHASE_BENCHMARK "PBM" // Benchmark (nesting multiple executions)
|
|
// Main phases, usable by all layers
|
|
#define NNTRACE_PHASE_INITIALIZATION "PI" // Initialization - not related to a model
|
|
#define NNTRACE_PHASE_PREPARATION "PP" // Model construction
|
|
#define NNTRACE_PHASE_COMPILATION "PC" // Model compilation
|
|
#define NNTRACE_PHASE_EXECUTION "PE" // Executing the model
|
|
#define NNTRACE_PHASE_TERMINATION "PT" // Tearing down
|
|
#define NNTRACE_PHASE_UNSPECIFIED "PU" // Helper code called from multiple phases
|
|
// Subphases of execution
|
|
#define NNTRACE_PHASE_INPUTS_AND_OUTPUTS "PIO" // Setting inputs/outputs and allocating buffers
|
|
#define NNTRACE_PHASE_TRANSFORMATION "PTR" // Transforming data for computation
|
|
#define NNTRACE_PHASE_COMPUTATION "PCO" // Computing operations' outputs
|
|
#define NNTRACE_PHASE_RESULTS "PR" // Reading out results
|
|
// Layers
|
|
#define NNTRACE_LAYER_APPLICATION "LA"
|
|
#define NNTRACE_LAYER_RUNTIME "LR"
|
|
#define NNTRACE_LAYER_IPC "LI"
|
|
#define NNTRACE_LAYER_DRIVER "LD"
|
|
#define NNTRACE_LAYER_CPU "LC"
|
|
#define NNTRACE_LAYER_OTHER "LO"
|
|
#define NNTRACE_LAYER_UTILITY "LU" // Code used from multiple layers
|
|
|
|
#ifndef NN_COMPATIBILITY_LIBRARY_BUILD
|
|
|
|
// Implementation
|
|
//
|
|
// Almost same as ATRACE_NAME, but enforcing explicit distinction between
|
|
// phase-per-scope and switching phases.
|
|
//
|
|
// Basic trace, one per scope allowed to enforce disjointness
|
|
#define NNTRACE_NAME_1(name) android::ScopedTrace ___tracer_1(ATRACE_TAG, name)
|
|
// Switching trace, more than one per scope allowed, translated by
|
|
// systrace_parser.py. This is mainly useful for tracing multiple phases through
|
|
// one function / scope.
|
|
#define NNTRACE_NAME_SWITCH(name) \
|
|
android::ScopedTrace PASTE(___tracer, __LINE__)(ATRACE_TAG, name); \
|
|
(void)___tracer_1 // ensure switch is only used after a basic trace
|
|
|
|
#else
|
|
|
|
#define NNTRACE_NAME_1(name) // empty
|
|
#define NNTRACE_NAME_SWITCH(name) // empty
|
|
|
|
#endif // NN_COMPATIBILITY_LIBRARY_BUILD
|
|
|
|
// Disallow use of raw ATRACE macros
|
|
#undef ATRACE_NAME
|
|
#undef ATRACE_CALL
|
|
|
|
#endif // ANDROID_FRAMEWORKS_ML_NN_COMMON_TRACING_H
|