Dokumen ini menjelaskan skema pembuatan versi op LiteRT. Pembuatan versi op memungkinkan developer menambahkan fungsi dan parameter baru ke op yang ada. Selain itu, layanan ini menjamin hal berikut:
- Kompatibilitas mundur: Implementasi LiteRT baru harus menangani file model lama.
- Kompatibilitas maju: Implementasi LiteRT lama harus menangani file model baru yang dihasilkan oleh konverter versi baru, selama tidak ada fitur baru yang digunakan.
- Deteksi kompatibilitas maju: Jika penerapan LiteRT lama membaca model baru yang berisi versi baru op yang tidak didukung, penerapan tersebut akan melaporkan error.
Contoh: Menambahkan dilatasi ke dalam konvolusi kedalaman
Bagian selanjutnya dari dokumen ini menjelaskan pembuatan versi op di TFLite dengan menunjukkan cara menambahkan parameter dilatasi ke operasi konvolusi kedalaman.
Pengetahuan tentang dilatasi tidak diperlukan untuk memahami dokumen ini. Perhatikan bahwa:
- 2 parameter bilangan bulat baru akan ditambahkan:
dilation_width_factor
dandilation_height_factor
. - Kernel konvolusi depthwise lama yang tidak mendukung dilatasi setara dengan menetapkan faktor dilatasi ke 1.
Mengubah skema FlatBuffer
Untuk menambahkan parameter baru ke op, ubah tabel opsi di
lite/schema/schema.fbs
.
Misalnya, tabel opsi konvolusi kedalaman terlihat seperti ini:
table DepthwiseConv2DOptions {
padding:Padding;
stride_w:int;
stride_h:int;
depth_multiplier:int;
fused_activation_function:ActivationFunctionType;
}
Saat menambahkan parameter baru:
- Tambahkan komentar yang menunjukkan parameter mana yang didukung oleh versi mana.
- Saat implementasi baru mendapatkan nilai default untuk parameter yang baru ditambahkan, implementasi tersebut akan berfungsi sama persis dengan implementasi lama.
Tabel akan terlihat seperti ini setelah parameter baru ditambahkan:
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;
}
File lite/schema/schema_generated.h
harus dibuat ulang untuk skema
baru.
Mengubah struktur C dan implementasi kernel
Di LiteRT, implementasi kernel dipisahkan dari definisi
FlatBuffer. Kernel membaca parameter dari struktur C yang ditentukan di
lite/c/builtin_op_data.h
.
Parameter konvolusi depthwise asli adalah sebagai berikut:
typedef struct {
TfLitePadding padding;
int stride_width;
int stride_height;
int depth_multiplier;
TfLiteFusedActivation activation;
} TfLiteDepthwiseConvParams;
Seperti skema FlatBuffer, tambahkan komentar yang menunjukkan parameter mana yang didukung mulai dari versi mana. Hasilnya dapat dilihat di bawah ini:
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;
Ubah juga implementasi kernel untuk membaca parameter yang baru ditambahkan dari struktur C. Detailnya dihilangkan di sini.
Mengubah kode pembacaan FlatBuffer
Logika untuk membaca FlatBuffer dan menghasilkan struktur C ada di
lite/core/api/flatbuffer_conversions.cc
.
Perbarui file untuk menangani parameter baru, seperti yang ditunjukkan di bawah ini:
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;
}
Anda tidak perlu memeriksa versi op di sini. Saat implementasi baru membaca file model lama yang tidak memiliki faktor dilatasi, implementasi baru akan menggunakan 1 sebagai nilai default, dan kernel baru akan berfungsi secara konsisten dengan kernel lama.
Mengubah pendaftaran kernel
MutableOpResolver (ditentukan di lite/mutable_op_resolver.h
) menyediakan beberapa
fungsi untuk mendaftarkan kernel op. Versi minimum dan maksimum adalah 1 secara
default:
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);
Operasi bawaan terdaftar di lite/kernels/register.cc
. Dalam contoh ini,
kami menerapkan kernel op baru yang dapat menangani DepthwiseConv2D
versi 1 dan
2, sehingga kita perlu mengubah baris ini:
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());
menjadi:
AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(),
/* min_version = */ 1,
/* max_version = */ 2);
Mengubah versi operasi TFLite
Langkah berikutnya adalah membuat TFLite mengisi versi minimum yang diperlukan untuk menjalankan operasi. Dalam contoh ini, artinya:
- Isi version=1 jika semua faktor dilatasi adalah 1.
- Isi version=2 jika tidak.
Ubah fungsi GetBuiltinOperatorVersion
untuk operator di
lite/tools/versioning/op_version.cc
dengan menambahkan versi baru ke kasus
DepthwiseConv2D
:
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;
Memperbarui peta versi operator
Langkah terakhir adalah menambahkan info versi baru ke peta versi operator. Langkah ini diperlukan karena kita perlu membuat versi runtime minimum yang diperlukan model berdasarkan peta versi ini.
Untuk melakukannya, Anda perlu menambahkan entri peta baru di
lite/tools/versioning/runtime_version.cc
.
Dalam contoh ini, Anda perlu menambahkan entri berikut ke op_version_map
:
{ {BuiltinOperator_DEPTHWISE_CONV_2D, 2}, %CURRENT_RUNTIME_VERSION%}
dengan %CURRENT_RUNTIME_VERSION%
sesuai dengan versi runtime saat ini
yang ditentukan di release_version.h.
Implementasi delegasi
LiteRT menyediakan API delegasi yang memungkinkan delegasi operasi ke
backend hardware. Dalam fungsi Prepare
delegasi, periksa apakah versi
didukung untuk setiap node dalam kode Delegasi.
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.
}
Hal ini diperlukan meskipun delegasi hanya mendukung operasi versi 1, sehingga delegasi dapat mendeteksi inkompatibilitas saat mendapatkan operasi versi yang lebih tinggi.