In diesem Dokument wird das Versionierungsschema für LiteRT-Betriebssysteme beschrieben. Mit der Versionierung von Vorgängen können Entwickler bestehenden Vorgängen neue Funktionen und Parameter hinzufügen. Außerdem werden folgende Garantien übernommen:
- Abwärtskompatibilität: Die neue LiteRT-Implementierung sollte eine alte Modelldatei verarbeiten.
- Vorwärtskompatibilität: Die alte LiteRT-Implementierung sollte eine neue Modelldatei verarbeiten, die mit der neuen Version des Converters erstellt wurde, sofern keine neuen Funktionen verwendet werden.
- Vorwärtskompatible Erkennung: Wenn eine alte LiteRT-Implementierung ein neues Modell liest, das eine neue Version einer nicht unterstützten Operation enthält, sollte der Fehler gemeldet werden.
Beispiel: Dilation in die richtungsabhängige Convolution einfügen
Im Rest dieses Dokuments wird die Versionierung von Operatoren in TFLite erläutert. Dabei wird gezeigt, wie Sie dem Vorgang der richtungsabhängigen Convolution Dilation-Parameter hinzufügen.
Für das Verständnis dieses Dokuments sind keine Kenntnisse über die Bildvergrößerung erforderlich. Hinweis:
- Es werden zwei neue Ganzzahlparameter hinzugefügt:
dilation_width_factor
unddilation_height_factor
. - Alte richtungsabhängige Convolution-Kernel, die keine Erweiterung unterstützen, entsprechen dem Festlegen der Erweiterungsfaktoren auf 1.
FlatBuffer-Schema ändern
Wenn Sie einer Operation neue Parameter hinzufügen möchten, ändern Sie die Optionstabelle in lite/schema/schema.fbs
.
Die Optionstabelle für die richtungsabhängige Konvolution sieht beispielsweise so aus:
table DepthwiseConv2DOptions {
padding:Padding;
stride_w:int;
stride_h:int;
depth_multiplier:int;
fused_activation_function:ActivationFunctionType;
}
Beachten Sie beim Hinzufügen neuer Parameter Folgendes:
- Fügen Sie Kommentare hinzu, in denen angegeben ist, welche Parameter von welcher Version unterstützt werden.
- Wenn die neue Implementierung die Standardwerte für neu hinzugefügte Parameter erhält, sollte sie genau wie die alte Implementierung funktionieren.
Die Tabelle sieht nach dem Hinzufügen der neuen Parameter so aus:
table DepthwiseConv2DOptions {
// Parameters for DepthwiseConv version 1 or above.
padding:Padding;
stride_w:int;
stride_h:int;
depth_multiplier:int;
fused_activation_function:ActivationFunctionType;
// Parameters for DepthwiseConv version 2 or above.
dilation_w_factor:int = 1;
dilation_h_factor:int = 1;
}
Die Datei lite/schema/schema_generated.h
sollte für das neue Schema neu generiert werden.
C-Strukturen und Kernelimplementierung ändern
In LiteRT ist die Kernelimplementierung von der FlatBuffer-Definition entkoppelt. Die Kernel lesen den Parameter aus C-Strukturen, die in lite/c/builtin_op_data.h
definiert sind.
Der ursprüngliche Parameter für die konvolutionsbasierte Tiefenverarbeitung sieht so aus:
typedef struct {
TfLitePadding padding;
int stride_width;
int stride_height;
int depth_multiplier;
TfLiteFusedActivation activation;
} TfLiteDepthwiseConvParams;
Fügen Sie wie beim FlatBuffer-Schema Kommentare hinzu, in denen angegeben ist, ab welcher Version welche Parameter unterstützt werden. Das Ergebnis sieht so aus:
typedef struct {
// Parameters for DepthwiseConv version 1 or above.
TfLitePadding padding;
int stride_width;
int stride_height;
int depth_multiplier;
TfLiteFusedActivation activation;
// Parameters for DepthwiseConv version 2 or above.
int dilation_width_factor;
int dilation_height_factor;
} TfLiteDepthwiseConvParams;
Bitte ändern Sie auch die Kernelimplementierung, damit die neu hinzugefügten Parameter aus den C-Strukturen gelesen werden. Die Details werden hier weggelassen.
FlatBuffer-Lesecode ändern
Die Logik zum Lesen von FlatBuffer und Erstellen der C-Struktur befindet sich in lite/core/api/flatbuffer_conversions.cc
.
Aktualisieren Sie die Datei, um die neuen Parameter zu verarbeiten, wie unten gezeigt:
TfLiteStatus ParseDepthwiseConv2D(const Operator* op,
ErrorReporter* error_reporter,
BuiltinDataAllocator* allocator,
void** builtin_data) {
CheckParsePointerParams(op, error_reporter, allocator, builtin_data);
SafeBuiltinDataAllocator safe_allocator(allocator);
std::unique_ptr<TfLiteDepthwiseConvParams,
SafeBuiltinDataAllocator::BuiltinDataDeleter>
params = safe_allocator.Allocate<TfLiteDepthwiseConvParams>();
TF_LITE_ENSURE(error_reporter, params != nullptr);
const DepthwiseConv2DOptions* schema_params =
op->builtin_options_as_DepthwiseConv2DOptions();
if (schema_params != nullptr) {
params->padding = ConvertPadding(schema_params->padding());
params->stride_width = schema_params->stride_w();
params->stride_height = schema_params->stride_h();
params->depth_multiplier = schema_params->depth_multiplier();
params->activation =
ConvertActivation(schema_params->fused_activation_function());
params->dilation_width_factor = schema_params->dilation_w_factor();
params->dilation_height_factor = schema_params->dilation_h_factor();
}
*builtin_data = params.release();
return kTfLiteOk;
}
Die Version des Betriebssystems muss hier nicht geprüft werden. Wenn die neue Implementierung eine alte Modelldatei liest, in der keine Vergrößerungsfaktoren vorhanden sind, wird „1“ als Standardwert verwendet. Der neue Kernel funktioniert dann konsistent mit dem alten Kernel.
Kernelregistrierung ändern
Der MutableOpResolver (definiert in lite/mutable_op_resolver.h
) bietet einige Funktionen zum Registrieren von Op-Kernels. Die Mindest- und Höchstversion sind standardmäßig 1:
void AddBuiltin(tflite::BuiltinOperator op, TfLiteRegistration* registration,
int min_version = 1, int max_version = 1);
void AddCustom(const char* name, TfLiteRegistration* registration,
int min_version = 1, int max_version = 1);
Die integrierten Vorgänge sind in lite/kernels/register.cc
registriert. In diesem Beispiel haben wir einen neuen OP-Kernel implementiert, der DepthwiseConv2D
Version 1 und 2 verarbeiten kann. Daher müssen wir diese Zeile ändern:
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());
in
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(),
/* min_version = */ 1,
/* max_version = */ 2);
TFLite-OP-Version ändern
Im nächsten Schritt müssen Sie TFLite anweisen, die Mindestversion zu verwenden, die für die Ausführung der Operation erforderlich ist. In diesem Beispiel bedeutet das:
- Geben Sie „version=1“ an, wenn alle Vergrößerungsfaktoren „1“ sind.
- Andernfalls „version=2“.
Ändern Sie die GetBuiltinOperatorVersion
-Funktion für den Operator in lite/tools/versioning/op_version.cc
, indem Sie dem Fall DepthwiseConv2D
die neue Version hinzufügen:
case BuiltinOperator_DEPTHWISE_CONV_2D:
auto depthwise_conv_params =
reinterpret_cast<TfLiteDepthwiseConvParams*>(op_sig.builtin_data);
TFLITE_DCHECK(depthwise_conv_params != nullptr);
if (depthwise_conv_params->dilation_width_factor != 1 ||
depthwise_conv_params->dilation_height_factor != 1) {
return 2;
}
return 1;
Zuordnung der Version des Mobilfunkanbieters aktualisieren
Im letzten Schritt fügen Sie die Informationen zur neuen Version in die Versionszuordnung des Mobilfunkanbieters ein. Dieser Schritt ist erforderlich, da wir die für das Modell erforderliche Mindestlaufzeitversion anhand dieser Versionszuordnung generieren müssen.
Dazu müssen Sie in lite/tools/versioning/runtime_version.cc
einen neuen Karteneintrag hinzufügen.
In diesem Beispiel müssen Sie op_version_map
den folgenden Eintrag hinzufügen:
{ {BuiltinOperator_DEPTHWISE_CONV_2D, 2}, %CURRENT_RUNTIME_VERSION%}
wobei %CURRENT_RUNTIME_VERSION%
der aktuellen Laufzeitversion entspricht, die in release_version.h definiert ist.
Implementierung der Delegierung
LiteRT bietet eine Delegations-API, mit der Operationen an Hardware-Back-Ends delegiert werden können. Prüfe in der Prepare
-Funktion des Deligierten, ob die Version für jeden Knoten im Delegationscode unterstützt wird.
const int kMaxVersion = 1;
TfLiteNode* node;
TfLiteRegistration* registration = nullptr;
TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration(context, node_index, &node, ®istration));
if (registration->version > kMaxVersion) {
// Reject the node if the version isn't supported.
}
Dies ist auch dann erforderlich, wenn die Deaktivierung nur Version 1-Vorgänge unterstützt, damit die Deaktivierung Inkompatibilitäten erkennen kann, wenn ein Vorgang einer höheren Version empfangen wird.