chore: import upstream snapshot with attribution
cffconvert / validate (push) Has been skipped
License Check / license-check (push) Failing after 2s

This commit is contained in:
wehub-resource-sync
2026-07-13 12:14:16 +08:00
commit 8a852e4b4e
36502 changed files with 9277225 additions and 0 deletions
+75
View File
@@ -0,0 +1,75 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("@rules_cc//cc:cc_test.bzl", "cc_test")
load("//tensorflow:tensorflow.default.bzl", "get_compatible_with_portable")
load("//tensorflow/lite:build_def.bzl", "tflite_copts")
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
cc_library(
name = "profiler",
srcs = ["profiler.cc"],
hdrs = ["profiler.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = [
":telemetry_status",
"//tensorflow/lite/core/api",
"//tensorflow/lite/profiling/telemetry/c:profiler",
"//tensorflow/lite/profiling/telemetry/c:telemetry_setting",
],
)
cc_library(
name = "telemetry",
srcs = ["telemetry.cc"],
hdrs = ["telemetry.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = [
":telemetry_status",
"//tensorflow/lite/core/api",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/profiling/telemetry/c:telemetry_setting",
],
)
cc_test(
name = "telemetry_test",
srcs = ["telemetry_test.cc"],
deps = [
":profiler",
":telemetry",
":telemetry_status",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/profiling/telemetry/c:telemetry_setting_internal",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "profiler_test",
srcs = ["profiler_test.cc"],
deps = [
":profiler",
":telemetry",
":telemetry_status",
"//tensorflow/lite/core/c:c_api_types",
"//tensorflow/lite/core/c:common",
"//tensorflow/lite/profiling/telemetry/c:telemetry_setting",
"@com_google_googletest//:gtest_main",
],
)
cc_library(
name = "telemetry_status",
hdrs = ["telemetry_status.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = ["//tensorflow/lite/core/c:c_api_types"],
)
@@ -0,0 +1,51 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")
load("//tensorflow:tensorflow.default.bzl", "get_compatible_with_portable")
load(
"//tensorflow/lite:build_def.bzl",
"tflite_cc_library_with_c_headers_test",
"tflite_copts",
)
package(
# copybara:uncomment default_applicable_licenses = ["//tensorflow:LICENSE"],
default_visibility = ["//visibility:public"],
licenses = ["notice"],
)
exports_files(
srcs = [
"profiler.h",
"telemetry_setting.h",
],
visibility = [
"//tensorflow/lite:__subpackages__",
],
)
tflite_cc_library_with_c_headers_test(
name = "profiler",
hdrs = ["profiler.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = [":telemetry_setting"],
)
tflite_cc_library_with_c_headers_test(
name = "telemetry_setting",
hdrs = ["telemetry_setting.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = [
":telemetry_setting_internal",
"//tensorflow/lite/core/c:common",
],
)
cc_library(
name = "telemetry_setting_internal",
srcs = ["telemetry_setting_internal.cc"],
hdrs = ["telemetry_setting_internal.h"],
compatible_with = get_compatible_with_portable(),
copts = tflite_copts(),
deps = ["//tensorflow/lite/core/c:common"],
)
@@ -0,0 +1,85 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_C_PROFILER_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_C_PROFILER_H_
#include <stdint.h>
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// C API for TFLite telemetry profiler.
// See C++ interface in tflite::telemetry::TelemetryProfiler.
// Note: This struct does not comply with ABI stability.
typedef struct TfLiteTelemetryProfilerStruct {
// Data that profiler needs to identify itself. This data is owned by the
// profiler. The profiler is owned in the user code, so the profiler is
// responsible for deallocating this when it is destroyed.
void* data;
// Reports a telemetry event with status.
// `event_name` indicates the name of the event (e.g. "Invoke") and should not
// be nullptr.
// `status`: uint64_t representation of TelemetryStatusCode.
void (*ReportTelemetryEvent)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, const char* event_name,
uint64_t status);
// Reports an op telemetry event with status.
// Same as `ReportTelemetryEvent`, with additional args `op_idx` and
// `subgraph_idx`.
// `status`: uint64_t representation of TelemetryStatusCode.
void (*ReportTelemetryOpEvent)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, const char* event_name,
int64_t op_idx, int64_t subgraph_idx, uint64_t status);
// Reports the model and interpreter settings.
// `setting_name` indicates the name of the setting and should not be nullptr.
// `settings`'s lifespan is not guaranteed outside the scope of
// `ReportSettings` call.
void (*ReportSettings)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, const char* setting_name,
const TfLiteTelemetrySettings* settings);
// Signals the beginning of an operator invocation.
// `op_name` is the name of the operator and should not be nullptr.
// Op invoke event are triggered with OPERATOR_INVOKE_EVENT type for TfLite
// ops and delegate kernels, and DELEGATE_OPERATOR_INVOKE_EVENT for delegate
// ops within a delegate kernels, if the instrumentation is in place.
// Returns event handle which can be passed to `EndOpInvokeEvent` later.
uint32_t (*ReportBeginOpInvokeEvent)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, const char* op_name,
int64_t op_idx, int64_t subgraph_idx);
// Signals the end to the event specified by `event_handle`.
void (*ReportEndOpInvokeEvent)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, uint32_t event_handle);
// For op / delegate op with built-in performance measurements, they
// are able to report the elapsed time directly.
// `elapsed_time` is in microsecond.
void (*ReportOpInvokeEvent)( // NOLINT
struct TfLiteTelemetryProfilerStruct* profiler, const char* op_name,
uint64_t elapsed_time, int64_t op_idx, int64_t subgraph_idx);
} TfLiteTelemetryProfilerStruct;
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_C_PROFILER_H_
@@ -0,0 +1,91 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_H_
#include <stddef.h>
#include <stdint.h>
#include "tensorflow/lite/core/c/common.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
// TFLite model, interpreter or delegate settings that will be reported by
// telemetry.
// Note: This struct does not comply with ABI stability.
typedef struct TfLiteTelemetrySettings {
// Source of the settings. Determines how `data` is interpreted.
// See tflite::telemetry::TelemetrySource for definition.
uint32_t source;
// Settings data. Interpretation based on `source`.
// If `source` is TFLITE_INTERPRETER, the type of `data` will
// be `TelemetryInterpreterSettings`.
// Otherwise, the data is provided by the individual delegate.
// Owned by the caller that exports TelemetrySettings (e.g. Interpreter).
const void* data;
} TfLiteTelemetrySettings;
typedef struct TfLiteTelemetryConversionMetadata
TfLiteTelemetryConversionMetadata;
const int32_t* TfLiteTelemetryConversionMetadataGetModelOptimizationModes(
const TfLiteTelemetryConversionMetadata* metadata);
size_t TfLiteTelemetryConversionMetadataGetNumModelOptimizationModes(
const TfLiteTelemetryConversionMetadata* metadata);
// TfLite model information and settings of the interpreter.
// Note: This struct does not comply with ABI stability.
typedef struct TfLiteTelemetryInterpreterSettings
TfLiteTelemetryInterpreterSettings;
const TfLiteTelemetryConversionMetadata*
TfLiteTelemetryInterpreterSettingsGetConversionMetadata(
const TfLiteTelemetryInterpreterSettings* settings);
// Telemetry data for a specific TFLite subgraph.
typedef struct TfLiteTelemetrySubgraphInfo TfLiteTelemetrySubgraphInfo;
size_t TfLiteTelemetryInterpreterSettingsGetNumSubgraphInfo(
const TfLiteTelemetryInterpreterSettings* settings);
const TfLiteTelemetrySubgraphInfo*
TfLiteTelemetryInterpreterSettingsGetSubgraphInfo(
const TfLiteTelemetryInterpreterSettings* settings);
size_t TfLiteTelemetrySubgraphInfoGetNumQuantizations(
TfLiteTelemetrySubgraphInfo* subgraph_info);
const TfLiteQuantization* TfLiteTelemetrySubgraphInfoGetQuantizations(
TfLiteTelemetrySubgraphInfo* subgraph_info);
// Telemetry information for GPU delegate.
typedef struct TfLiteTelemetryGpuDelegateSettings
TfLiteTelemetryGpuDelegateSettings;
size_t TfLiteTelemetryGpuDelegateSettingsGetNumNodesDelegated(
const TfLiteTelemetryGpuDelegateSettings* settings);
int TfLiteTelemetryGpuDelegateSettingsGetBackend(
const TfLiteTelemetryGpuDelegateSettings* settings);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_H_
@@ -0,0 +1,78 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting_internal.h"
#include <cstddef>
#include <cstdint>
extern "C" {
const TfLiteTelemetryConversionMetadata*
TfLiteTelemetryInterpreterSettingsGetConversionMetadata(
const TfLiteTelemetryInterpreterSettings* settings) {
if (settings == nullptr) return nullptr;
return settings->conversion_metadata.get();
}
const int32_t* TfLiteTelemetryConversionMetadataGetModelOptimizationModes(
const TfLiteTelemetryConversionMetadata* metadata) {
if (metadata == nullptr) return nullptr;
return metadata->model_optimization_modes.data();
}
size_t TfLiteTelemetryConversionMetadataGetNumModelOptimizationModes(
const TfLiteTelemetryConversionMetadata* metadata) {
if (metadata == nullptr) return 0;
return metadata->model_optimization_modes.size();
}
size_t TfLiteTelemetryInterpreterSettingsGetNumSubgraphInfo(
const TfLiteTelemetryInterpreterSettings* settings) {
if (settings == nullptr) return 0;
return settings->subgraph_infos.size();
}
const TfLiteTelemetrySubgraphInfo*
TfLiteTelemetryInterpreterSettingsGetSubgraphInfo(
const TfLiteTelemetryInterpreterSettings* settings) {
if (settings == nullptr) return nullptr;
return settings->subgraph_infos.data();
}
size_t TfLiteTelemetrySubgraphInfoGetNumQuantizations(
TfLiteTelemetrySubgraphInfo* subgraph_info) {
if (subgraph_info == nullptr) return 0;
return subgraph_info->quantizations.size();
}
const TfLiteQuantization* TfLiteTelemetrySubgraphInfoGetQuantizations(
TfLiteTelemetrySubgraphInfo* subgraph_info) {
if (subgraph_info == nullptr) return nullptr;
return subgraph_info->quantizations.data();
}
size_t TfLiteTelemetryGpuDelegateSettingsGetNumNodesDelegated(
const TfLiteTelemetryGpuDelegateSettings* settings) {
if (settings == nullptr) return 0;
return settings->num_nodes_delegated;
}
int TfLiteTelemetryGpuDelegateSettingsGetBackend(
const TfLiteTelemetryGpuDelegateSettings* settings) {
if (settings == nullptr) return 0;
return settings->backend;
}
} // extern "C"
@@ -0,0 +1,58 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_INTERNAL_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_INTERNAL_H_
#include <cstdint>
#include <memory>
#include <vector>
#include "tensorflow/lite/core/c/common.h"
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
struct TfLiteTelemetryConversionMetadata {
std::vector<int32_t> model_optimization_modes;
};
struct TfLiteTelemetrySubgraphInfo {
std::vector<TfLiteQuantization> quantizations;
};
struct TfLiteTelemetryInterpreterSettings {
std::unique_ptr<TfLiteTelemetryConversionMetadata> conversion_metadata;
std::vector<TfLiteTelemetrySubgraphInfo> subgraph_infos;
};
struct TfLiteTelemetryGpuDelegateSettings {
// Reported by "GpuDelegate::DelegatePrepare" event.
size_t num_nodes_delegated;
// Reported by "GpuDelegateKernel::Prepare" event.
enum Backend : int {
UNKNOWN = 0,
OPENCL = 1,
OPENGL = 2,
};
Backend backend;
};
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_C_TELEMETRY_SETTING_INTERNAL_H_
@@ -0,0 +1,158 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/lite/profiling/telemetry/profiler.h"
#include <cstdint>
#include "tensorflow/lite/core/api/profiler.h"
namespace tflite::telemetry {
void TelemetryProfiler::AddEvent(const char* tag, EventType event_type,
uint64_t metric, int64_t event_metadata1,
int64_t event_metadata2) {
switch (event_type) {
case EventType::TELEMETRY_EVENT:
case EventType::TELEMETRY_DELEGATE_EVENT: {
// When the event_metadata1 is set to -1, the event is not associated
// with a particular op. See telemetry.cc.
if (event_metadata1 == -1) {
ReportTelemetryEvent(tag, TelemetryStatusCode(metric));
} else {
ReportTelemetryOpEvent(tag, event_metadata1, event_metadata2,
TelemetryStatusCode(metric));
}
break;
}
case EventType::OPERATOR_INVOKE_EVENT:
case EventType::DELEGATE_OPERATOR_INVOKE_EVENT:
case EventType::DELEGATE_PROFILED_OPERATOR_INVOKE_EVENT: {
ReportOpInvokeEvent(tag, metric, event_metadata1, event_metadata2);
break;
}
default:
// Rejects other event types.
return;
}
}
void TelemetryProfiler::AddEventWithData(const char* tag, EventType event_type,
const void* data) {
switch (event_type) {
case EventType::TELEMETRY_REPORT_SETTINGS:
case EventType::TELEMETRY_DELEGATE_REPORT_SETTINGS: {
auto* settings = reinterpret_cast<const TfLiteTelemetrySettings*>(data);
if (settings) {
ReportSettings(tag, settings);
}
break;
}
default:
// No other AddEventWithData will be accepted for telemetry.
return;
}
}
uint32_t TelemetryProfiler::BeginEvent(const char* tag, EventType event_type,
int64_t event_metadata1,
int64_t event_metadata2) {
switch (event_type) {
case EventType::OPERATOR_INVOKE_EVENT:
case EventType::DELEGATE_OPERATOR_INVOKE_EVENT:
case EventType::DELEGATE_PROFILED_OPERATOR_INVOKE_EVENT: {
return ReportBeginOpInvokeEvent(tag, event_metadata1, event_metadata2);
}
default:
// Telemetry Profiler does not accept other event types with BeginEvent.
return UINT32_MAX;
}
}
void TelemetryProfiler::EndEvent(uint32_t event_handle) {
if (event_handle == UINT32_MAX) return;
ReportEndOpInvokeEvent(event_handle);
}
// This TfLiteTelemetryProfiler class wraps the `TfLiteTelemetryProfilerStruct`
// C API into the TelemetryProfiler interface. Users that uses the C API
// will provide `TfLiteTelemetryProfilerStruct` to TfLiteInterpreter and then
// TFLite runtime will build `TfLiteTelemetryProfiler` with it and register to
// the interpreter.
class TfLiteTelemetryProfiler : public TelemetryProfiler {
public:
explicit TfLiteTelemetryProfiler(TfLiteTelemetryProfilerStruct* profiler)
: profiler_(profiler) {}
void ReportTelemetryEvent(const char* event_name,
TelemetryStatusCode status) override;
void ReportTelemetryOpEvent(const char* event_name, int64_t op_idx,
int64_t subgraph_idx,
TelemetryStatusCode status) override;
void ReportSettings(const char* setting_name,
const TfLiteTelemetrySettings* settings) override;
uint32_t ReportBeginOpInvokeEvent(const char* op_name, int64_t op_idx,
int64_t subgraph_idx) override;
void ReportEndOpInvokeEvent(uint32_t event_handle) override;
void ReportOpInvokeEvent(const char* op_name, uint64_t elapsed_time,
int64_t op_idx, int64_t subgraph_idx) override;
private:
// Owned by TfLiteTelemetryProfiler.
// Note, profiler_->data is owned by the caller.
TfLiteTelemetryProfilerStruct* profiler_ = nullptr;
};
void TfLiteTelemetryProfiler::ReportTelemetryEvent(const char* event_name,
TelemetryStatusCode status) {
profiler_->ReportTelemetryEvent(profiler_, event_name, status.code());
}
void TfLiteTelemetryProfiler::ReportTelemetryOpEvent(
const char* event_name, int64_t op_idx, int64_t subgraph_idx,
TelemetryStatusCode status) {
profiler_->ReportTelemetryOpEvent(profiler_, event_name, op_idx, subgraph_idx,
status.code());
}
void TfLiteTelemetryProfiler::ReportSettings(
const char* setting_name, const TfLiteTelemetrySettings* settings) {
profiler_->ReportSettings(profiler_, setting_name, settings);
}
uint32_t TfLiteTelemetryProfiler::ReportBeginOpInvokeEvent(
const char* op_name, int64_t op_idx, int64_t subgraph_idx) {
return profiler_->ReportBeginOpInvokeEvent(profiler_, op_name, op_idx,
subgraph_idx);
}
void TfLiteTelemetryProfiler::ReportEndOpInvokeEvent(uint32_t event_handle) {
profiler_->ReportEndOpInvokeEvent(profiler_, event_handle);
}
void TfLiteTelemetryProfiler::ReportOpInvokeEvent(const char* op_name,
uint64_t elapsed_time,
int64_t op_idx,
int64_t subgraph_idx) {
profiler_->ReportOpInvokeEvent(profiler_, op_name, elapsed_time, op_idx,
subgraph_idx);
}
TelemetryProfiler* MakeTfLiteTelemetryProfiler(
TfLiteTelemetryProfilerStruct* profiler) {
return new TfLiteTelemetryProfiler(profiler);
}
} // namespace tflite::telemetry
@@ -0,0 +1,104 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_PROFILER_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_PROFILER_H_
#include <cstdint>
#include "tensorflow/lite/core/api/profiler.h"
#include "tensorflow/lite/profiling/telemetry/c/profiler.h"
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting.h"
#include "tensorflow/lite/profiling/telemetry/telemetry_status.h"
namespace tflite::telemetry {
// Telemetry profiler interface.
// When installed, the telemetry profilers accepts profiler events exported from
// TFLite runtime profiler instrumentation points, interprets the events
// based on the event type and forward to corresponding `Report` function.
// The implementation of the `Report` functions are responsible for dumping the
// profiling events to the data sink.
// The implementation of TelemetryProfiler is required to be thread safe.
class TelemetryProfiler : public Profiler {
public:
// General Telemetry events.
// Reports a telemetry event with status.
// `event_name` indicates the name of the event (e.g. "Invoke") and should not
// be nullptr.
// `status` shows 1) the source of the event, interpreter or which delegate,
// 2) the return status of the event.
virtual void ReportTelemetryEvent(const char* event_name,
TelemetryStatusCode status) = 0;
// Reports an op telemetry event with status.
// Same as `ReportTelemetryEvent`, with additional args `op_idx` and
// `subgraph_idx`.
virtual void ReportTelemetryOpEvent(const char* event_name, int64_t op_idx,
int64_t subgraph_idx,
TelemetryStatusCode status) = 0;
// Telemetry ReportSettings events.
// Reports the model and interpreter settings.
// `setting_name` indicates the name of the setting and should not be nullptr.
// `settings`'s lifespan is not guaranteed outside the scope of
// `ReportSettings` call.
virtual void ReportSettings(const char* setting_name,
const TfLiteTelemetrySettings* settings) = 0;
// Performance measurement events.
// Signals the beginning of an operator invocation.
// `op_name` is the name of the operator and should not be nullptr.
// Op invoke event are triggered with OPERATOR_INVOKE_EVENT type for TfLite
// ops and delegate kernels, and DELEGATE_OPERATOR_INVOKE_EVENT for delegate
// ops within a delegate kernels, if the instrumentation is in place.
// Returns event handle which can be passed to `EndOpInvokeEvent` later.
virtual uint32_t ReportBeginOpInvokeEvent(const char* op_name, int64_t op_idx,
int64_t subgraph_idx) = 0;
// Signals the end to the event specified by `event_handle`.
virtual void ReportEndOpInvokeEvent(uint32_t event_handle) = 0;
// For op / delegate op with built-in performance measurements, they
// are able to report the elapsed time directly.
// `elapsed_time` is in microsecond.
virtual void ReportOpInvokeEvent(const char* op_name, uint64_t elapsed_time,
int64_t op_idx, int64_t subgraph_idx) = 0;
private:
// Methods inherited from TfLite Profiler.
// TelemetryProfiler will dispatch the event signals to appropriate `Report`
// functinos defined above based on the event type.
// Subclasses should not override those following methods.
void AddEvent(const char* tag, EventType event_type, uint64_t metric,
int64_t event_metadata1, int64_t event_metadata2) final;
void AddEventWithData(const char* tag, EventType event_type,
const void* data) final;
uint32_t BeginEvent(const char* tag, EventType event_type,
int64_t event_metadata1, int64_t event_metadata2) final;
void EndEvent(uint32_t event_handle) final;
};
// Creates a concrete TelemetryProfiler that wraps the
// `TfLiteTelemetryProfilerStruct` C API.
TelemetryProfiler* MakeTfLiteTelemetryProfiler(
TfLiteTelemetryProfilerStruct* profiler);
} // namespace tflite::telemetry
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_PROFILER_H_
@@ -0,0 +1,154 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/lite/profiling/telemetry/profiler.h"
#include <cstdint>
#include <memory>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting.h"
#include "tensorflow/lite/profiling/telemetry/telemetry_status.h"
namespace tflite::telemetry {
namespace {
constexpr char kEventName[] = "event_name";
constexpr char kSettingName[] = "setting_name";
class MockTelemtryProfiler : public TelemetryProfiler {
public:
MOCK_METHOD(void, ReportTelemetryEvent,
(const char* event_name, TelemetryStatusCode status), (override));
MOCK_METHOD(void, ReportTelemetryOpEvent,
(const char* event_name, int64_t op_idx, int64_t subgraph_idx,
TelemetryStatusCode status),
(override));
MOCK_METHOD(void, ReportSettings,
(const char* setting_name,
const TfLiteTelemetrySettings* settings),
(override));
MOCK_METHOD(uint32_t, ReportBeginOpInvokeEvent,
(const char* op_name, int64_t op_idx, int64_t subgraph_idx),
(override));
MOCK_METHOD(void, ReportEndOpInvokeEvent, (uint32_t event_handle),
(override));
MOCK_METHOD(void, ReportOpInvokeEvent,
(const char* op_name, uint64_t elapsed_time, int64_t op_idx,
int64_t subgraph_idx),
(override));
};
class TelemetryStructTest : public ::testing::Test {
protected:
TelemetryStructTest() {
context_.profiler = &profiler_;
profiler_struct_.data = &mock_profiler_;
profiler_struct_.ReportTelemetryEvent =
[](struct TfLiteTelemetryProfilerStruct* profiler,
const char* event_name, uint64_t status) {
static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportTelemetryEvent(
event_name, tflite::telemetry::TelemetryStatusCode(status));
};
profiler_struct_.ReportTelemetryOpEvent =
[](struct TfLiteTelemetryProfilerStruct* profiler,
const char* event_name, int64_t op_idx, int64_t subgraph_idx,
uint64_t status) {
static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportTelemetryOpEvent(
event_name, op_idx, subgraph_idx,
tflite::telemetry::TelemetryStatusCode(status));
};
profiler_struct_.ReportSettings =
[](struct TfLiteTelemetryProfilerStruct* profiler,
const char* setting_name, const TfLiteTelemetrySettings* settings) {
static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportSettings(setting_name, settings);
};
profiler_struct_.ReportBeginOpInvokeEvent =
[](struct TfLiteTelemetryProfilerStruct* profiler, const char* op_name,
int64_t op_idx, int64_t subgraph_idx) -> uint32_t {
return static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportBeginOpInvokeEvent(op_name, op_idx, subgraph_idx);
};
profiler_struct_.ReportEndOpInvokeEvent =
[](struct TfLiteTelemetryProfilerStruct* profiler,
uint32_t event_handle) {
return static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportEndOpInvokeEvent(event_handle);
};
profiler_struct_.ReportOpInvokeEvent =
[](struct TfLiteTelemetryProfilerStruct* profiler, const char* op_name,
uint64_t elapsed_time, int64_t op_idx, int64_t subgraph_idx) {
return static_cast<MockTelemtryProfiler*>(profiler->data)
->ReportOpInvokeEvent(op_name, elapsed_time, op_idx,
subgraph_idx);
};
profiler_.reset(telemetry::MakeTfLiteTelemetryProfiler(&profiler_struct_));
}
MockTelemtryProfiler mock_profiler_;
std::unique_ptr<TelemetryProfiler> profiler_;
TfLiteContext context_;
TfLiteTelemetryProfilerStruct profiler_struct_;
};
TEST_F(TelemetryStructTest, TelemetryReportEvent) {
EXPECT_CALL(mock_profiler_,
ReportTelemetryEvent(kEventName, TelemetryStatusCode(kTfLiteOk)));
profiler_->ReportTelemetryEvent(kEventName, TelemetryStatusCode(kTfLiteOk));
}
TEST_F(TelemetryStructTest, TelemetryReportOpEvent) {
EXPECT_CALL(
mock_profiler_,
ReportTelemetryOpEvent(kEventName, 1, 2, TelemetryStatusCode(kTfLiteOk)));
profiler_->ReportTelemetryOpEvent(kEventName, 1, 2,
TelemetryStatusCode(kTfLiteOk));
}
TEST_F(TelemetryStructTest, TelemetryReportSettings) {
EXPECT_CALL(mock_profiler_, ReportSettings(kSettingName, testing::_));
TfLiteTelemetrySettings settings{};
profiler_->ReportSettings(kSettingName, &settings);
}
TEST_F(TelemetryStructTest, TelemetryReportBeginOpInvokeEvent) {
EXPECT_CALL(mock_profiler_, ReportBeginOpInvokeEvent(kSettingName, 1, 2));
profiler_->ReportBeginOpInvokeEvent(kSettingName, 1, 2);
}
TEST_F(TelemetryStructTest, TelemetryReportEndOpInvokeEvent) {
EXPECT_CALL(mock_profiler_, ReportEndOpInvokeEvent(1));
profiler_->ReportEndOpInvokeEvent(1);
}
TEST_F(TelemetryStructTest, TelemetryReportOpInvokeEvent) {
EXPECT_CALL(mock_profiler_, ReportOpInvokeEvent(kSettingName, 1, 2, 3));
profiler_->ReportOpInvokeEvent(kSettingName, 1, 2, 3);
}
} // namespace
} // namespace tflite::telemetry
@@ -0,0 +1,98 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/lite/profiling/telemetry/telemetry.h"
#include <cstdint>
#include "tensorflow/lite/core/api/profiler.h"
#include "tensorflow/lite/profiling/telemetry/telemetry_status.h"
namespace tflite::telemetry {
void TelemetryReportEvent(TfLiteContext* context, const char* event_name,
TfLiteStatus status) {
if (context->profiler) {
reinterpret_cast<Profiler*>(context->profiler)
->AddEvent(event_name, Profiler::EventType::TELEMETRY_EVENT,
TelemetryStatusCode(status).code(),
/*event_metadata=*/-1);
}
}
void TelemetryReportOpEvent(TfLiteContext* context, const char* op_name,
int64_t op_index, int64_t subgraph_index,
TfLiteStatus status) {
if (context->profiler) {
reinterpret_cast<Profiler*>(context->profiler)
->AddEvent(op_name, Profiler::EventType::TELEMETRY_EVENT,
TelemetryStatusCode(status).code(), op_index,
subgraph_index);
}
}
void TelemetryReportDelegateEvent(TfLiteContext* context,
const char* event_name,
TelemetrySource source, uint32_t code) {
if (context->profiler) {
reinterpret_cast<Profiler*>(context->profiler)
->AddEvent(event_name, Profiler::EventType::TELEMETRY_DELEGATE_EVENT,
TelemetryStatusCode(source, code).code(),
/*event_metadata=*/-1);
}
}
void TelemetryReportDelegateOpEvent(TfLiteContext* context, const char* op_name,
int64_t op_index, int64_t subgraph_index,
TelemetrySource source, uint32_t code) {
if (context->profiler) {
reinterpret_cast<Profiler*>(context->profiler)
->AddEvent(op_name, Profiler::EventType::TELEMETRY_DELEGATE_EVENT,
TelemetryStatusCode(source, code).code(), op_index,
subgraph_index);
}
}
void TelemetryReportSettings(
TfLiteContext* context, const char* setting_name,
const TfLiteTelemetryInterpreterSettings* settings) {
auto* profiler = reinterpret_cast<Profiler*>(context->profiler);
if (profiler) {
TfLiteTelemetrySettings telemetry_settings{};
telemetry_settings.source =
static_cast<uint32_t>(TelemetrySource::TFLITE_INTERPRETER);
telemetry_settings.data = reinterpret_cast<const void*>(settings);
profiler->AddEventWithData(
setting_name, Profiler::EventType::TELEMETRY_REPORT_SETTINGS,
reinterpret_cast<const void*>(&telemetry_settings));
}
}
void TelemetryReportDelegateSettings(TfLiteContext* context,
const char* setting_name,
TelemetrySource source,
const void* settings) {
auto* profiler = reinterpret_cast<Profiler*>(context->profiler);
if (profiler) {
TfLiteTelemetrySettings telemetry_settings{};
telemetry_settings.source = static_cast<uint32_t>(source);
telemetry_settings.data = settings;
profiler->AddEventWithData(
setting_name, Profiler::EventType::TELEMETRY_DELEGATE_REPORT_SETTINGS,
reinterpret_cast<const void*>(&telemetry_settings));
}
}
} // namespace tflite::telemetry
@@ -0,0 +1,75 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_H_
#include <cstdint>
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting.h"
#include "tensorflow/lite/profiling/telemetry/telemetry_status.h"
namespace tflite::telemetry {
// Methods for instrumenting TFLite runtime to export telemetry events to
// profilers.
// Reports an interpreter telemetry event.
// `event_name` indicates the name of the event (e.g. "Invoke") and should not
// be nullptr.
void TelemetryReportEvent(TfLiteContext* context, const char* event_name,
TfLiteStatus status);
// Reports an interpreter telemetry event associated with an op.
// `op_name` indicates the name of the op and should not be nullptr.
void TelemetryReportOpEvent(TfLiteContext* context, const char* op_name,
int64_t op_index, int64_t subgraph_index,
TfLiteStatus status);
// Reports a delegate telemetry event.
// `event_name` indicates the name of the event (e.g. "Invoke") and should not
// be nullptr.
// `source` indicates which delegate the event is from.
// `code` is the error code from the delegate.
void TelemetryReportDelegateEvent(TfLiteContext* context,
const char* event_name,
TelemetrySource source, uint32_t code);
// Reports a delegate telemetry event associated with an op.
// `op_name` indicates the name of the op and should not be nullptr.
void TelemetryReportDelegateOpEvent(TfLiteContext* context, const char* op_name,
int64_t op_index, int64_t subgraph_index,
TelemetrySource source, uint32_t code);
// Reports model and interpreter level settings.
// `setting_name` indicates the name of the setting.
void TelemetryReportSettings(
TfLiteContext* context, const char* setting_name,
const TfLiteTelemetryInterpreterSettings* settings);
// Reports delegate settings.
// `setting_name` indicates the name of the setting.
// `source` indicates which delegate the event is from.
// `settings` is the delegate provided settings and should not be nullptr.
void TelemetryReportDelegateSettings(TfLiteContext* context,
const char* setting_name,
TelemetrySource source,
const void* settings);
} // namespace tflite::telemetry
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_H_
@@ -0,0 +1,70 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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 TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_STATUS_H_
#define TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_STATUS_H_
#include <cstdint>
#include "tensorflow/lite/core/c/c_api_types.h"
namespace tflite::telemetry {
// The source of a telemetry event. Enum values intentionally follow proto
// guidelines as they are used for Clearcut logging.
enum class TelemetrySource : uint32_t {
UNKNOWN = 0,
TFLITE_INTERPRETER = 1,
// For external delegate.
// External delegate should identify themselves in telemetry event names by
// prefixing the delegame name to it.
TFLITE_CUSTOM_DELEGATE = 2,
TFLITE_GPU = 3,
TFLITE_NNAPI = 4,
TFLITE_HEXAGON = 5,
TFLITE_XNNPACK = 6,
TFLITE_COREML = 7,
};
// A namespaced status code for telemetry events.
struct TelemetryStatusCode {
TelemetrySource source = TelemetrySource::TFLITE_INTERPRETER;
uint32_t status_code = 0;
// Helper constructors to build the status code from various types.
TelemetryStatusCode() = default;
TelemetryStatusCode(TelemetrySource source, uint32_t status_code)
: source(source), status_code(status_code) {}
explicit TelemetryStatusCode(TfLiteStatus status)
: TelemetryStatusCode(TelemetrySource::TFLITE_INTERPRETER, status) {}
explicit TelemetryStatusCode(uint64_t code)
: TelemetryStatusCode(static_cast<TelemetrySource>(code >> 32),
static_cast<uint32_t>(code)) {}
// Returns the uint64_t representation of the status code.
uint64_t code() const {
return (static_cast<uint64_t>(source) << 32 | status_code);
}
bool operator==(const TelemetryStatusCode& other) const {
return source == other.source && status_code == other.status_code;
}
};
} // namespace tflite::telemetry
#endif // TENSORFLOW_LITE_PROFILING_TELEMETRY_TELEMETRY_STATUS_H_
@@ -0,0 +1,114 @@
/* Copyright 2022 The TensorFlow Authors. All Rights Reserved.
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.
==============================================================================*/
#include "tensorflow/lite/profiling/telemetry/telemetry.h"
#include <cstdint>
#include <string>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "tensorflow/lite/core/c/c_api_types.h"
#include "tensorflow/lite/core/c/common.h"
#include "tensorflow/lite/profiling/telemetry/c/telemetry_setting_internal.h"
#include "tensorflow/lite/profiling/telemetry/profiler.h"
#include "tensorflow/lite/profiling/telemetry/telemetry_status.h"
namespace tflite::telemetry {
namespace {
constexpr char kEventName[] = "event_name";
constexpr char kSettingName[] = "setting_name";
class MockTelemetryProfiler : public TelemetryProfiler {
public:
MOCK_METHOD(void, ReportTelemetryEvent,
(const char* event_name, TelemetryStatusCode status), (override));
MOCK_METHOD(void, ReportTelemetryOpEvent,
(const char* event_name, int64_t op_idx, int64_t subgraph_idx,
TelemetryStatusCode status),
(override));
MOCK_METHOD(void, ReportSettings,
(const char* setting_name,
const TfLiteTelemetrySettings* settings),
(override));
MOCK_METHOD(uint32_t, ReportBeginOpInvokeEvent,
(const char* op_name, int64_t op_idx, int64_t subgraph_idx),
(override));
MOCK_METHOD(void, ReportEndOpInvokeEvent, (uint32_t event_handle),
(override));
MOCK_METHOD(void, ReportOpInvokeEvent,
(const char* op_name, uint64_t elapsed_time, int64_t op_idx,
int64_t subgraph_idx),
(override));
};
class TelemetryTest : public ::testing::Test {
protected:
TelemetryTest() { context_.profiler = &profiler_; }
MockTelemetryProfiler profiler_;
TfLiteContext context_;
};
TEST_F(TelemetryTest, TelemetryReportEvent) {
EXPECT_CALL(profiler_,
ReportTelemetryEvent(kEventName, TelemetryStatusCode(kTfLiteOk)));
TelemetryReportEvent(&context_, kEventName, kTfLiteOk);
}
TEST_F(TelemetryTest, TelemetryReportOpEvent) {
EXPECT_CALL(profiler_, ReportTelemetryOpEvent(
kEventName, 1, 2, TelemetryStatusCode(kTfLiteOk)));
TelemetryReportOpEvent(&context_, kEventName, 1, 2, kTfLiteOk);
}
TEST_F(TelemetryTest, TelemetryReportDelegateEvent) {
EXPECT_CALL(profiler_, ReportTelemetryEvent(
kEventName, TelemetryStatusCode(
TelemetrySource::TFLITE_GPU, 21)));
TelemetryReportDelegateEvent(&context_, kEventName,
TelemetrySource::TFLITE_GPU, 21);
}
TEST_F(TelemetryTest, TelemetryReportDelegateOpEvent) {
EXPECT_CALL(profiler_,
ReportTelemetryOpEvent(
kEventName, 1, 2,
TelemetryStatusCode(TelemetrySource::TFLITE_GPU, 21)));
TelemetryReportDelegateOpEvent(&context_, kEventName, 1, 2,
TelemetrySource::TFLITE_GPU, 21);
}
TEST_F(TelemetryTest, TelemetryReportSettings) {
EXPECT_CALL(profiler_, ReportSettings(kSettingName, testing::_));
TfLiteTelemetryInterpreterSettings settings{};
TelemetryReportSettings(&context_, kSettingName, &settings);
}
TEST_F(TelemetryTest, TelemetryReportDelegateSettings) {
std::string settings = "gpu delegate settings";
EXPECT_CALL(profiler_, ReportSettings(kSettingName, testing::_));
TelemetryReportDelegateSettings(&context_, kSettingName,
TelemetrySource::TFLITE_GPU, &settings);
}
} // namespace
} // namespace tflite::telemetry