إصدارات مشغل LiteRT

يصف هذا المستند مخطط إصدارات عمليات LiteRT. إصدارات العمليات لتمكين المطورين من إضافة وظائف ومعلمات جديدة إلى العمليات الحالية. بالإضافة إلى ذلك، تضمن ما يلي:

  • التوافق مع الأنظمة القديمة: يجب أن يتعامل تنفيذ LiteRT الجديد مع ملف النموذج القديم.
  • التوافق مع إعادة التوجيه: يجب أن يتعامل تنفيذ LiteRT القديم مع ملف نموذجي جديد تم إنتاجه من خلال الإصدار الجديد من أداة التحويل، طالما لم يتم ميزات جديدة.
  • اكتشاف توافق إعادة التوجيه: في حالة تنفيذ LiteRT قديم نموذج جديد يحتوي على إصدار جديد من عملية ليست يتم دعمه، فينبغي أن يبلغ عن الخطأ.

مثال: إضافة الامتداد إلى التفاف العمق

يوضح الجزء المتبقي من هذا المستند إصدارات العمليات في TFLite من خلال توضيح كيفية لإضافة معاملات التوسع إلى عملية الالتفاف بعمق.

معرفة التوسيع غير مطلوبة لفهم هذا المستند. تجدر الإشارة إلى ما يلي:

  • ستتم إضافة مَعلمتَين جديدتَين لعدد صحيح: dilation_width_factor و dilation_height_factor
  • نواة الالتفاف القديمة التي لا تدعم التوسّع مكافئة إلى تعيين عوامل التوسع على 1.

تغيير مخطط FlatBuffer

لإضافة معلمات جديدة إلى عملية، غيِّر جدول الخيارات في lite/schema/schema.fbs

على سبيل المثال، يبدو جدول الخيارات الخاص بالتحايل على العمق على النحو التالي:

table DepthwiseConv2DOptions {
  padding:Padding;
  stride_w:int;
  stride_h:int;
  depth_multiplier:int;
  fused_activation_function:ActivationFunctionType;
}

عند إضافة مَعلمات جديدة:

  • إضافة تعليقات تشير إلى المعلَمات المتوافقة مع كل إصدار
  • عندما تحصل عملية التنفيذ الجديدة على القيم التلقائية للقيم المضافة حديثًا فإن طريقة التنفيذ يجب أن تعمل تمامًا مثل طريقة التنفيذ القديمة.

سيظهر الجدول على النحو التالي بعد إضافة المعلمات الجديدة:

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;
}

يجب إعادة إنشاء الملف lite/schema/schema_generated.h للملف الجديد Google.

تغيير هياكل C وتنفيذ النواة

في LiteRT، يتم فصل تنفيذ النواة عن FlatBuffer. التعريف. تقرأ النواة المعامل من البُنى C المحددة في lite/c/builtin_op_data.h

في ما يلي معلَمة الالتفاف depthwise الأصلية:

typedef struct {
  TfLitePadding padding;
  int stride_width;
  int stride_height;
  int depth_multiplier;
  TfLiteFusedActivation activation;
} TfLiteDepthwiseConvParams;

وكما هو الحال مع مخطط FlatBuffer، أضِف تعليقات تشير إلى المعلَمات مدعومة بدءًا من أي إصدار. يتم عرض النتيجة أدناه:

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;

يُرجى أيضًا تغيير تنفيذ النواة لقراءة المعلمات المضافة حديثًا. من الهياكل C. تم حذف التفاصيل هنا.

تغيير رمز قراءة FlatBuffer

منطق قراءة FlatBuffer وإنتاج هيكل C موجود lite/core/api/flatbuffer_conversions.cc

عدِّل الملف لاستيعاب المَعلمات الجديدة، كما هو موضّح أدناه:

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;
}

لا يلزم التحقق من إصدار العملية هنا. موعد تنفيذ العملية الجديدة ملف نموذجي قديم حيث تكون عوامل التمديد مفقودة، فسيستخدم الرقم 1 القيمة الافتراضية، وستعمل النواة الجديدة بشكل متوافق مع النواة القديمة.

تغيير تسجيل النواة

يقدّم برنامج MutableOp النشر (المحدّد في lite/mutable_op_resolver.h) بعض النقاط لتسجيل نواة العمليات. الحد الأدنى والأقصى للإصدار هو 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);

العمليات المدمجة مسجّلة في lite/kernels/register.cc. في هذا المثال، أطلقنا نواة تشغيل جديدة يمكنها التعامل مع الإصدار 1 من DepthwiseConv2D 2، لذا سنحتاج إلى تغيير هذا السطر:

AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D());

إلى:

AddBuiltin(BuiltinOperator_DEPTHWISE_CONV_2D, Register_DEPTHWISE_CONV_2D(),
             /* min_version = */ 1,
             /* max_version = */ 2);

تغيير إصدار عملية TFLite

الخطوة التالية هي جعل TFLite يملأ الحد الأدنى من الإصدار المطلوب لتنفيذ العملية. وفي هذا المثال، يعني ذلك ما يلي:

  • تعبئة الإصدار=1 عندما تكون عوامل التوسع كلها تساوي 1.
  • تعبئة الإصدار=2 بخلاف ذلك.

تعديل الدالة GetBuiltinOperatorVersion لعامل التشغيل في lite/tools/versioning/op_version.cc عن طريق إضافة الإصدار الجديد إلى حالة 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;

تعديل خريطة إصدار منظِّم الجولات

الخطوة الأخيرة هي إضافة معلومات الإصدار الجديد إلى خريطة إصدار عامل التشغيل. هذا النمط خطوة مطلوبة لأننا نحتاج إلى إنشاء الحد الأدنى المطلوب إصدار بيئة التشغيل على أساس خريطة الإصدار هذه.

للقيام بذلك، تحتاج إلى إضافة إدخال خريطة جديد في lite/tools/versioning/runtime_version.cc

في هذا المثال، يجب إضافة الإدخال التالي إلى op_version_map:

{ {BuiltinOperator_DEPTHWISE_CONV_2D, 2}, %CURRENT_RUNTIME_VERSION%}

حيث تتجاوب %CURRENT_RUNTIME_VERSION% مع إصدار بيئة التشغيل الحالي محدد في tensorflow/core/public/version.h.

تنفيذ عملية التفويض

يوفر LiteRT واجهة برمجة تطبيقات للتفويض تتيح تفويض العمليات إلى الخلفيات الخاصة بالأجهزة. في وظيفة Prepare للمفوِّض، تحقّق مما إذا كان الإصدار متوافقًا متوافقة مع كل عقدة في رمز التفويض.

const int kMaxVersion = 1;
TfLiteNode* node;
TfLiteRegistration* registration = nullptr;
TF_LITE_ENSURE_STATUS(context->GetNodeAndRegistration(context, node_index, &node, &registration));

if (registration->version > kMaxVersion) {
  // Reject the node if the version isn't supported.
}

يُعد هذا مطلوبًا حتى إذا كان التفويض يدعم عمليات الإصدار 1 فقط، وبالتالي فإن يمكن للتفويض اكتشاف عدم التوافق عند الحصول على عملية إصدار أعلى.