blob: f5b7fa7a1c1d7793c8c5aecc047a911287cfbffc [file] [log] [blame]
/*
Copyright 2018 Google LLC
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.
==============================================================================*/
//
// This header file defines EdgeTpuManager, and EdgeTpuContext.
// EdgeTpuContext is an object associated with one or more tflite::Interpreter.
// Instances of this class should be allocated through
// EdgeTpuManager::NewEdgeTpuContext.
// More than one Interpreter instances can point to the same context. This means
// the tasks from both would be executed under the same TPU context.
// The lifetime of this context must be longer than all associated
// tflite::Interpreter instances.
//
// Typical usage with NNAPI:
//
// std::unique_ptr<tflite::Interpreter> interpreter;
// tflite::ops::builtin::BuiltinOpResolver resolver;
// auto model =
// tflite::FlatBufferModel::BuildFromFile(model_file_name.c_str());
//
// // Registers edge TPU custom op handler with Tflite resolver.
// resolver.AddCustom(edgetpu::kCustomOp, edgetpu::RegisterCustomOp());
//
// tflite::InterpreterBuilder(*model, resolver)(&interpreter);
//
// interpreter->AllocateTensors();
// .... (Prepare input tensors)
// interpreter->Invoke();
// .... (retrieving the result from output tensors)
//
// // Releases interpreter instance to free up resources associated with
// // this custom op.
// interpreter.reset();
//
// Typical usage with Non-NNAPI:
//
// // Sets up the tpu_context.
// auto tpu_context =
// edgetpu::EdgeTpuManager::GetSingleton()->OpenDevice();
//
// std::unique_ptr<tflite::Interpreter> interpreter;
// tflite::ops::builtin::BuiltinOpResolver resolver;
// auto model =
// tflite::FlatBufferModel::BuildFromFile(model_file_name.c_str());
//
// // Registers edge TPU custom op handler with Tflite resolver.
// resolver.AddCustom(edgetpu::kCustomOp, edgetpu::RegisterCustomOp());
//
// tflite::InterpreterBuilder(*model, resolver)(&interpreter);
//
// // Binds a context with a specific interpreter.
// interpreter->SetExternalContext(kTfLiteEdgeTpuContext,
// tpu_context.get());
//
// // Note that all edge TPU context set ups should be done before this
// // function is called.
// interpreter->AllocateTensors();
// .... (Prepare input tensors)
// interpreter->Invoke();
// .... (retrieving the result from output tensors)
//
// // Releases interpreter instance to free up resources associated with
// // this custom op.
// interpreter.reset();
//
// // Closes the edge TPU.
// tpu_context.reset();
#ifndef TFLITE_PUBLIC_EDGETPU_H_
#define TFLITE_PUBLIC_EDGETPU_H_
// If the ABI changes in a backward-incompatible way, please increment the
// version number in the BUILD file.
// LINT.IfChange()
#include <memory>
#include <ostream>
#include <string>
#include <unordered_map>
#include <vector>
#include "tensorflow/lite/context.h"
namespace edgetpu {
// EdgeTPU custom op.
static const char kCustomOp[] = "edgetpu-custom-op";
enum class DeviceType {
kApexPci = 0,
kApexUsb = 1,
};
class EdgeTpuContext;
// Singleton edge TPU manager for allocating new TPU contexts.
// Functions in this interface are thread-safe.
class EdgeTpuManager {
public:
using DeviceOptions = std::unordered_map<std::string, std::string>;
struct DeviceEnumerationRecord {
DeviceType type;
std::string path;
// Returns true if two enumeration records point to the same device.
friend bool operator==(const DeviceEnumerationRecord& lhs,
const DeviceEnumerationRecord& rhs) {
return (lhs.type == rhs.type) && (lhs.path == rhs.path);
}
// Returns true if two enumeration records point to defferent devices.
friend bool operator!=(const DeviceEnumerationRecord& lhs,
const DeviceEnumerationRecord& rhs) {
return !(lhs == rhs);
}
};
// Returns pointer to the singleton object, or nullptr if not supported on
// this platform.
static EdgeTpuManager* GetSingleton();
// NewEdgeTpuContext family functions has been deprecated and will be removed
// in the future. Please use OpenDevice for new code.
//
// These functions return an unique_ptr to EdgeTpuContext, with
// the intention that the device will be closed, and associate resources
// released, when the unique_ptr leaves scope.
//
// These functions seek exclusive ownership of the opened devices. As they
// cannot open devices already opened by OpenDevice, and vice versa.
// Devices opened through these functions would have attribute
// "ExclusiveOwnership", which can be queried through
// #EdgeTpuContext::GetDeviceOptions().
// Creates a new Edge TPU context to be assigned to Tflite::Interpreter. The
// Edge TPU context is associated with the default TPU device. May be null
// if underlying device cannot be found or open. Caller owns the returned new
// context and should destroy the context either implicity or explicitly after
// all interpreters sharing this context are destroyed.
virtual std::unique_ptr<EdgeTpuContext> NewEdgeTpuContext() = 0;
// Same as above, but the created context is associated with the specified
// type.
virtual std::unique_ptr<EdgeTpuContext> NewEdgeTpuContext(
DeviceType device_type) = 0;
// Same as above, but the created context is associated with the specified
// type and device path.
virtual std::unique_ptr<EdgeTpuContext> NewEdgeTpuContext(
DeviceType device_type, const std::string& device_path) = 0;
// Same as above, but the created context is associated with the given device
// type, path and options.
//
// Available options are:
// - "Performance": ["Low", "Medium", "High", "Max"] (Default is "Max")
// - "Usb.AlwaysDfu": ["True", "False"] (Default is "False")
// - "Usb.MaxBulkInQueueLength": ["0",.., "255"] (Default is "32")
virtual std::unique_ptr<EdgeTpuContext> NewEdgeTpuContext(
DeviceType device_type, const std::string& device_path,
const DeviceOptions& options) = 0;
// Enumerates all connected Edge TPU devices.
virtual std::vector<DeviceEnumerationRecord> EnumerateEdgeTpu() const = 0;
// OpenDevice family of functions return a shared_ptr to EdgeTpuContext, with
// the intention that the device can be shared among multiple software
// components.
//
// These functions seek shared ownership of the opened devices. As they
// cannot open devices already opened by NewEdgeTpuContext, and vice versa.
// The device would be closed after the last reference leaves scope.
// Opens the default Edge TPU device.
//
// Multiple invocations of this function could return handle to the same
// device, but there is no guarantee.
//
// Returns a shared pointer to Edge TPU device. The shared_ptr could point to
// nullptr in case of error.
virtual std::shared_ptr<EdgeTpuContext> OpenDevice() = 0;
// Same as above, but the returned context is associated with the specified
// type.
virtual std::shared_ptr<EdgeTpuContext> OpenDevice(
DeviceType device_type) = 0;
// Same as above, but the returned context is associated with the specified
// type and device path. If path is empty, any device of the specified type
// could be returned.
virtual std::shared_ptr<EdgeTpuContext> OpenDevice(
DeviceType device_type, const std::string& device_path) = 0;
// Same as above, but the specified options would used to create a new context
// if no existing device is compatible with the specified type and path.
//
// If a device of compatible type and path can be found, the options could be
// ignored. It is the caller's responsibility to verify if the returned
// context is desirable, through #EdgeTpuContext::GetDeviceOptions().
//
// Available options are:
// - "Performance": ["Low", "Medium", "High", "Max"] (Default is "Max")
// - "Usb.AlwaysDfu": ["True", "False"] (Default is "False")
// - "Usb.MaxBulkInQueueLength": ["0",.., "255"] (Default is "32")
virtual std::shared_ptr<EdgeTpuContext> OpenDevice(
DeviceType device_type, const std::string& device_path,
const DeviceOptions& options) = 0;
// Returns a snapshot of currently opened shareable devices.
// Exclusively owned Edge TPU devices cannot be returned here, as they're
// owned by unique pointers.
virtual std::vector<std::shared_ptr<EdgeTpuContext>> GetOpenedDevices()
const = 0;
// Sets verbosity of operating logs related to edge TPU.
// Verbosity level can be set to [0-10], in which 10 is the most verbose.
virtual TfLiteStatus SetVerbosity(int verbosity) = 0;
// Returns the version of EdgeTPU runtime stack.
virtual std::string Version() const = 0;
protected:
// No deletion for this singleton instance.
virtual ~EdgeTpuManager() = default;
};
// External context to be assigned through
// tflite::Interpreter::SetExternalContext.
// One should get hold of either shared_ptr from EdgeTpuManager::OpenDevice, or
// unique_ptr from EdgeTpuManager::NewEdgeTpuContext, to ensure ownership, and
// avoid using this pointer directly.
// Functions in this interface are thread-safe.
class EdgeTpuContext : public TfLiteExternalContext {
public:
virtual ~EdgeTpuContext() = 0;
// Returns a pointer to the device enumeration record for this device,
// if available.
virtual const EdgeTpuManager::DeviceEnumerationRecord& GetDeviceEnumRecord()
const = 0;
// Returns a snapshot of the options used to open this
// device, and current state, if available.
//
// Supported attributes are:
// - "ExclusiveOwnership": present when it is under exclusive ownership
// (unique_ptr returned by NewEdgeTpuContext).
// - "IsReady": present when it is ready for further requests.
virtual EdgeTpuManager::DeviceOptions GetDeviceOptions() const = 0;
// Returns true if the device is most likely ready to accept requests.
// When there are fatal errors, including unplugging of an USB device, the
// state of this device would be changed.
virtual bool IsReady() const = 0;
};
// Returns pointer to an instance of TfLiteRegistration to handle
// EdgeTPU custom ops, to be used with
// tflite::ops::builtin::BuiltinOpResolver::AddCustom
TfLiteRegistration* RegisterCustomOp();
// Inserts name of device type into ostream. Returns the modified ostream.
std::ostream& operator<<(std::ostream& out, DeviceType device_type);
} // namespace edgetpu
// LINT.ThenChange(BUILD:version)
#endif // TFLITE_PUBLIC_EDGETPU_H_