Delegado do LiteRT Core ML

O LiteRT Core ML delegado permite executar modelos LiteRT em framework Core ML, que resulta em uma inferência de modelo mais rápida em dispositivos iOS.

Dispositivos e versões com iOS compatíveis:

  • iOS 12 e mais recente Nas versões mais antigas do iOS, o delegado do Core ML substituto automaticamente para a CPU.
  • Por padrão, o delegado do Core ML só vai ser ativado em dispositivos com SoC A12 e posteriores (iPhone Xs e versões mais recentes) para usar o Neural Engine para inferência mais rápida. Se você também quiser usar o delegado do Core ML em dispositivos mais antigos, consulte práticas recomendadas

Modelos compatíveis

No momento, o delegado do Core ML oferece suporte a modelos flutuantes (FP32 e FP16).

Como testar o delegado do Core ML no seu próprio modelo

O delegado do Core ML já está incluído na versão noturna do LiteRT CocoaPods. Para usar o delegado do Core ML, altere seu pod LiteRT para incluir a subespecificação CoreML no seu Podfile.

target 'YourProjectName'
  pod 'TensorFlowLiteSwift/CoreML', '~> 2.4.0'  # Or TensorFlowLiteObjC/CoreML

OU

# Particularily useful when you also want to include 'Metal' subspec.
target 'YourProjectName'
  pod 'TensorFlowLiteSwift', '~> 2.4.0', :subspecs => ['CoreML']

Swift

    let coreMLDelegate = CoreMLDelegate()
    var interpreter: Interpreter

    // Core ML delegate will only be created for devices with Neural Engine
    if coreMLDelegate != nil {
      interpreter = try Interpreter(modelPath: modelPath,
                                    delegates: [coreMLDelegate!])
    } else {
      interpreter = try Interpreter(modelPath: modelPath)
    }
  

Objective-C

    // Import module when using CocoaPods with module support
    @import TFLTensorFlowLite;

    // Or import following headers manually
    # import "tensorflow/lite/objc/apis/TFLCoreMLDelegate.h"
    # import "tensorflow/lite/objc/apis/TFLTensorFlowLite.h"

    // Initialize Core ML delegate
    TFLCoreMLDelegate* coreMLDelegate = [[TFLCoreMLDelegate alloc] init];

    // Initialize interpreter with model path and Core ML delegate
    TFLInterpreterOptions* options = [[TFLInterpreterOptions alloc] init];
    NSError* error = nil;
    TFLInterpreter* interpreter = [[TFLInterpreter alloc]
                                    initWithModelPath:modelPath
                                              options:options
                                            delegates:@[ coreMLDelegate ]
                                                error:&error];
    if (error != nil) { /* Error handling... */ }

    if (![interpreter allocateTensorsWithError:&error]) { /* Error handling... */ }
    if (error != nil) { /* Error handling... */ }

    // Run inference ...
  

C (até a versão 2.3.0)

    #include "tensorflow/lite/delegates/coreml/coreml_delegate.h"

    // Initialize interpreter with model
    TfLiteModel* model = TfLiteModelCreateFromFile(model_path);

    // Initialize interpreter with Core ML delegate
    TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
    TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(NULL);  // default config
    TfLiteInterpreterOptionsAddDelegate(options, delegate);
    TfLiteInterpreterOptionsDelete(options);

    TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);

    TfLiteInterpreterAllocateTensors(interpreter);

    // Run inference ...

    /* ... */

    // Dispose resources when it is no longer used.
    // Add following code to the section where you dispose of the delegate
    // (e.g. `dealloc` of class).

    TfLiteInterpreterDelete(interpreter);
    TfLiteCoreMlDelegateDelete(delegate);
    TfLiteModelDelete(model);
      

Práticas recomendadas

Como usar o delegado do Core ML em dispositivos sem o Neural Engine

Por padrão, o delegado do Core ML só será criado se o dispositivo tiver Engine, e vai retornar null se o delegado não for criado. Se você quiser execute o delegado do Core ML em outros ambientes (por exemplo, simulador), transmita .all. como uma opção ao criar um delegado no Swift. Em C++ (e Objective-C), é possível transmitir TfLiteCoreMlDelegateAllDevices. O exemplo a seguir mostra como fazer isso:

Swift

    var options = CoreMLDelegate.Options()
    options.enabledDevices = .all
    let coreMLDelegate = CoreMLDelegate(options: options)!
    let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [coreMLDelegate])
      

Objective-C

    TFLCoreMLDelegateOptions* coreMLOptions = [[TFLCoreMLDelegateOptions alloc] init];
    coreMLOptions.enabledDevices = TFLCoreMLDelegateEnabledDevicesAll;
    TFLCoreMLDelegate* coreMLDelegate = [[TFLCoreMLDelegate alloc]
                                          initWithOptions:coreMLOptions];

    // Initialize interpreter with delegate
  

C

    TfLiteCoreMlDelegateOptions options;
    options.enabled_devices = TfLiteCoreMlDelegateAllDevices;
    TfLiteDelegate* delegate = TfLiteCoreMlDelegateCreate(&options);
    // Initialize interpreter with delegate
      

Como usar o delegado Metal(GPU) como substituto.

Quando o delegado do Core ML não for criado, ainda será possível usar Delegado do Metal para receber benefícios de desempenho. O exemplo a seguir mostra como fazer isso:

Swift

    var delegate = CoreMLDelegate()
    if delegate == nil {
      delegate = MetalDelegate()  // Add Metal delegate options if necessary.
    }

    let interpreter = try Interpreter(modelPath: modelPath,
                                      delegates: [delegate!])
  

Objective-C

    TFLDelegate* delegate = [[TFLCoreMLDelegate alloc] init];
    if (!delegate) {
      // Add Metal delegate options if necessary
      delegate = [[TFLMetalDelegate alloc] init];
    }
    // Initialize interpreter with delegate
      

C

    TfLiteCoreMlDelegateOptions options = {};
    delegate = TfLiteCoreMlDelegateCreate(&options);
    if (delegate == NULL) {
      // Add Metal delegate options if necessary
      delegate = TFLGpuDelegateCreate(NULL);
    }
    // Initialize interpreter with delegate
      

A lógica de criação do delegado lê o ID de máquina do dispositivo (por exemplo, iPhone11,1) para determinar a disponibilidade do neural Engine. Consulte a código para mais detalhes. Também é possível implementar seu próprio conjunto de dispositivos que usam outras bibliotecas, DeviceKit.

Como usar uma versão mais antiga do Core ML

Embora o iOS 13 seja compatível com o Core ML 3, o modelo pode funcionar melhor convertidos com a especificação de modelo do Core ML 2. A versão da conversão desejada é é definida como a versão mais recente por padrão, mas é possível alterar isso definindo coreMLVersion (em Swift, coreml_version na API C) na opção delegado para versão mais antiga.

Operações compatíveis

As operações seguintes são compatíveis com o delegado do Core ML.

  • Foram adicionados:
    • Apenas certas formas podem ser transmitidas. No layout de tensores do Core ML, seguintes formas de tensor são transmitidas. [B, C, H, W], [B, C, 1, 1], [B, 1, H, W], [B, 1, 1, 1].
  • GrupoMédio 2D
  • Concat
    • A concatenação deve ser feita ao longo do eixo do canal.
  • Conv2D
    • Os pesos e os vieses devem ser constantes.
  • DepthwiseConv2D
    • Os pesos e os vieses devem ser constantes.
  • Totalmente conectada (também conhecida como "Dense" ou "InnerProduct")
    • Os pesos e o viés (se houver) devem ser constantes.
    • Aceita apenas casos de lote único. As dimensões de entrada devem ser 1, exceto a última dimensão.
  • Hardswish
  • Logística (também conhecida como sigmoide)
  • MaxPool2D
  • MirrorPad
    • Somente a entrada 4D com o modo REFLECT é compatível. O padding deve ser e só é permitida para as dimensões H e W.
  • Mul
    • Apenas certas formas podem ser transmitidas. No layout de tensores do Core ML, seguintes formas de tensor são transmitidas. [B, C, H, W], [B, C, 1, 1], [B, 1, H, W], [B, 1, 1, 1].
  • Pad e PadV2
    • Somente a entrada 4D é compatível. O padding deve ser constante e só permitido para as dimensões H e W.
  • Relu
  • ReluN1To1
  • Relu6
  • Remodelar
    • Suportado apenas quando a versão do Core ML de destino é 2, não compatível quando para o Core ML 3.
  • ResizeBilinear
  • SoftMax
  • Tanh
  • TransposeConv
    • Os pesos devem ser constantes.

Feedback

Em caso de problemas, crie uma GitHub com todos os detalhes necessários para a reprodução.

Perguntas frequentes

  • O CoreML delegado oferece suporte a substituto para CPU se um gráfico contiver ops?
    • Sim
  • O delegado do CoreML funciona no simulador de iOS?
    • Sim. A biblioteca inclui destinos x86 e x86_64 para que possa ser executada um simulador, mas não haverá melhoria de desempenho em relação à CPU.
  • O delegado do LiteRT e do CoreML é compatível com o MacOS?
    • O LiteRT é testado apenas no iOS, mas não no MacOS.
  • Há suporte para as operações personalizadas do LiteRT?
    • Não, o delegado do CoreML não é compatível com operações personalizadas e será substituído CPU.

APIs