Помогают защитить Большой Барьерный Риф с TensorFlow на Kaggle Присоединяйтесь вызов

Делегат графического процессора TensorFlow Lite

TensorFlow Lite поддерживает несколько аппаратных ускорителей. В этом документе описывается, как использовать серверную часть графического процессора с помощью API-интерфейсов делегата TensorFlow Lite на Android и iOS.

Графические процессоры предназначены для обеспечения высокой пропускной способности для массово распараллеливаемых рабочих нагрузок. Таким образом, они хорошо подходят для глубоких нейронных сетей, которые состоят из огромного количества операторов, каждый из которых работает с некоторым входным тензором (-ами), которые можно легко разделить на меньшие рабочие нагрузки и выполнять параллельно, что обычно приводит к меньшей задержке. В лучшем случае логический вывод на графическом процессоре теперь может выполняться достаточно быстро для ранее недоступных приложений реального времени.

В отличие от ЦП, графические процессоры выполняют вычисления с 16-битными или 32-битными числами с плавающей запятой и не требуют квантования для оптимальной производительности. Делегат действительно принимает 8-битные квантованные модели, но вычисление будет выполняться в числах с плавающей запятой. Обратитесь к расширенному документации для деталей.

Еще одним преимуществом вывода графического процессора является его энергоэффективность. Графические процессоры выполняют вычисления очень эффективным и оптимизированным образом, поэтому они потребляют меньше энергии и выделяют меньше тепла, чем при выполнении той же задачи на процессорах.

Учебные пособия по демонстрационному приложению

Самый простой способ опробовать делегат GPU - это следовать приведенным ниже руководствам, в которых рассказывается о создании наших демонстрационных классификационных приложений с поддержкой GPU. Код GPU пока только двоичный; в ближайшее время он будет открыт с открытым исходным кодом. Как только вы поймете, как заставить наши демонстрации работать, вы можете попробовать это на своих собственных моделях.

Android (с Android Studio)

Для учебника шаг за шагом, смотреть GPU Делегат для Android видео.

Шаг 1. Клонируйте исходный код TensorFlow и откройте его в Android Studio.

git clone https://github.com/tensorflow/tensorflow

Шаг 2. Изменить app/build.gradle использовать каждую ночь GPU AAR

Добавьте tensorflow-lite-gpu пакет наряду с существующим tensorflow-lite пакета в существующих dependencies блока.

dependencies {
    ...
    implementation 'org.tensorflow:tensorflow-lite:2.3.0'
    implementation 'org.tensorflow:tensorflow-lite-gpu:2.3.0'
}

Шаг 3. Сборка и запуск

Выполнить → Запустить приложение. Когда вы запустите приложение, вы увидите кнопку для включения графического процессора. Измените квантованную модель на модель с плавающей запятой, а затем щелкните GPU, чтобы запустить на GPU.

запустить демонстрацию графического процессора Android и переключиться на графический процессор

iOS (с XCode)

Для учебника шаг за шагом, смотрите GPU делегатом для IOS видео.

Шаг 1. Получите исходный код демонстрации и убедитесь, что он компилируется.

Следуйте нашим IOS Demo App учебник . Это приведет вас к тому моменту, когда на вашем телефоне будет работать немодифицированная демоверсия камеры iOS.

Шаг 2. Измените Podfile, чтобы использовать CocoaPod с графическим процессором TensorFlow Lite.

Начиная с версии 2.3.0, по умолчанию делегат графического процессора исключается из модуля, чтобы уменьшить двоичный размер. Вы можете включить их, указав подспецификацию. Для TensorFlowLiteSwift стручка:

pod 'TensorFlowLiteSwift/Metal', '~> 0.0.1-nightly',

ИЛИ

pod 'TensorFlowLiteSwift', '~> 0.0.1-nightly', :subspecs => ['Metal']

Вы можете сделать так же для TensorFlowLiteObjC или TensorFlowLitC , если вы хотите использовать Objective-C (от 2.4.0 выпуска) или C API.

До выпуска 2.3.0

До TensorFlow Lite 2.0.0

Мы создали двоичный CocoaPod, который включает делегат GPU. Чтобы переключить проект на его использование, измените файл `tensorflow / tensorflow / lite / examples / ios / camera / Podfile`, чтобы использовать модуль` TensorFlowLiteGpuExperimental` вместо `TensorFlowLite`.


    target 'YourProjectName'
      # pod 'TensorFlowLite', '1.12.0'
      pod 'TensorFlowLiteGpuExperimental'
    

До версии TensorFlow Lite 2.2.0

Начиная с TensorFlow Lite 2.1.0 и до 2.2.0, делегат GPU включен в модуль TensorFlowLiteC. Вы можете выбирать между «TensorFlowLiteC» и «TensorFlowLiteSwift» в зависимости от языка.

Шаг 3. Включите делегат GPU

Для того, чтобы включить код , который будет использовать GPU делегата, вам нужно будет изменить TFLITE_USE_GPU_DELEGATE от 0 до 1 в CameraExampleViewController.h .

#define TFLITE_USE_GPU_DELEGATE 1

Шаг 4. Создайте и запустите демонстрационное приложение.

Выполнив предыдущий шаг, вы сможете запустить приложение.

Шаг 5. Режим выпуска

На шаге 4 вы работали в режиме отладки, чтобы повысить производительность, вам следует перейти на сборку выпуска с соответствующими оптимальными настройками Metal. В частности, изменить эти настройки перейдите к Product > Scheme > Edit Scheme... . Выберите Run . На Info вкладке Изменение Build Configuration с Debug на Release , снимите флажок Debug executable .

настройка выпуска

Затем щелкните Options вкладку и изменить GPU Frame Capture для Disabled и Metal API Validation на Disabled .

настройка параметров металла

Наконец, не забудьте выбрать сборки только для выпуска на 64-разрядной архитектуре. Под Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings набор Build Active Architecture Only > Release Да.

настройка параметров выпуска

Пробуем делегат графического процессора на вашей собственной модели

Android

Есть два способа запуска модели ускорения в зависимости от того, если вы используете Android Studio ML Model Binding или TensorFlow Lite интерпретатора.

Интерпретатор TensorFlow Lite

Посмотрите демонстрацию, чтобы узнать, как добавить делегата. В приложении, добавьте AAR , как указано выше, импорт org.tensorflow.lite.gpu.GpuDelegate модуля и использовать addDelegate функцию , чтобы зарегистрировать GPU делегатом на переводчика:

Котлин

    import org.tensorflow.lite.Interpreter
    import org.tensorflow.lite.gpu.CompatibilityList
    import org.tensorflow.lite.gpu.GpuDelegate

    val compatList = CompatibilityList()

    val options = Interpreter.Options().apply{
        if(compatList.isDelegateSupportedOnThisDevice){
            // if the device has a supported GPU, add the GPU delegate
            val delegateOptions = compatList.bestOptionsForThisDevice
            this.addDelegate(GpuDelegate(delegateOptions))
        } else {
            // if the GPU is not supported, run on 4 threads
            this.setNumThreads(4)
        }
    }

    val interpreter = Interpreter(model, options)

    // Run inference
    writeToInput(input)
    interpreter.run(input, output)
    readFromOutput(output)
      

Джава

    import org.tensorflow.lite.Interpreter;
    import org.tensorflow.lite.gpu.CompatibilityList;
    import org.tensorflow.lite.gpu.GpuDelegate;

    // Initialize interpreter with GPU delegate
    Interpreter.Options options = new Interpreter.Options();
    CompatibilityList compatList = CompatibilityList();

    if(compatList.isDelegateSupportedOnThisDevice()){
        // if the device has a supported GPU, add the GPU delegate
        GpuDelegate.Options delegateOptions = compatList.getBestOptionsForThisDevice();
        GpuDelegate gpuDelegate = new GpuDelegate(delegateOptions);
        options.addDelegate(gpuDelegate);
    } else {
        // if the GPU is not supported, run on 4 threads
        options.setNumThreads(4);
    }

    Interpreter interpreter = new Interpreter(model, options);

    // Run inference
    writeToInput(input);
    interpreter.run(input, output);
    readFromOutput(output);
      

iOS

Быстрый

    import TensorFlowLite

    // Load model ...

    // Initialize TensorFlow Lite interpreter with the GPU delegate.
    let delegate = MetalDelegate()
    if let interpreter = try Interpreter(modelPath: modelPath,
                                         delegates: [delegate]) {
      // Run inference ...
    }
      

Цель-C

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

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

    // Initialize GPU delegate
    TFLMetalDelegate* metalDelegate = [[TFLMetalDelegate alloc] init];

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

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

    // Run inference ...

        ```
          

C (до 2.3.0)

        #include "tensorflow/lite/c/c_api.h"
        #include "tensorflow/lite/delegates/gpu/metal_delegate.h"

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

        // Initialize interpreter with GPU delegate
        TfLiteInterpreterOptions* options = TfLiteInterpreterOptionsCreate();
        TfLiteDelegate* delegate = TFLGPUDelegateCreate(nil);  // default config
        TfLiteInterpreterOptionsAddDelegate(options, metal_delegate);
        TfLiteInterpreter* interpreter = TfLiteInterpreterCreate(model, options);
        TfLiteInterpreterOptionsDelete(options);

        TfLiteInterpreterAllocateTensors(interpreter);

        NSMutableData *input_data = [NSMutableData dataWithLength:input_size * sizeof(float)];
        NSMutableData *output_data = [NSMutableData dataWithLength:output_size * sizeof(float)];
        TfLiteTensor* input = TfLiteInterpreterGetInputTensor(interpreter, 0);
        const TfLiteTensor* output = TfLiteInterpreterGetOutputTensor(interpreter, 0);

        // Run inference
        TfLiteTensorCopyFromBuffer(input, inputData.bytes, inputData.length);
        TfLiteInterpreterInvoke(interpreter);
        TfLiteTensorCopyToBuffer(output, outputData.mutableBytes, outputData.length);

        // Clean up
        TfLiteInterpreterDelete(interpreter);
        TFLGpuDelegateDelete(metal_delegate);
        TfLiteModelDelete(model);
          

## Supported Models and Ops

With the release of the GPU delegate, we included a handful of models that can
be run on the backend:

*   [MobileNet v1 (224x224) image classification](https://ai.googleblog.com/2017/06/mobilenets-open-source-models-for.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobilenet_v1_1.0_224.tflite)
    <br /><i>(image classification model designed for mobile and embedded based vision applications)</i>
*   [DeepLab segmentation (257x257)](https://ai.googleblog.com/2018/03/semantic-image-segmentation-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/deeplabv3_257_mv_gpu.tflite)
    <br /><i>(image segmentation model that assigns semantic labels (e.g., dog, cat, car) to every pixel in the input image)</i>
*   [MobileNet SSD object detection](https://ai.googleblog.com/2018/07/accelerated-training-and-inference-with.html) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/mobile_ssd_v2_float_coco.tflite)
    <br /><i>(image classification model that detects multiple objects with bounding boxes)</i>
*   [PoseNet for pose estimation](https://github.com/tensorflow/tfjs-models/tree/master/posenet) [[download]](https://storage.googleapis.com/download.tensorflow.org/models/tflite/gpu/multi_person_mobilenet_v1_075_float.tflite)
    <br /><i>(vision model that estimates the poses of a person(s) in image or video)</i>

To see a full list of supported ops, please see the
[advanced documentation](gpu_advanced).

## Non-supported models and ops

If some of the ops are not supported by the GPU delegate, the framework will
only run a part of the graph on the GPU and the remaining part on the CPU. Due
to the high cost of CPU/GPU synchronization, a split execution mode like this
will often result in slower performance than when the whole network is run on
the CPU alone. In this case, the user will get a warning like:

```none
WARNING: op code #42 cannot be handled by this delegate.
```

Мы не обеспечивали обратный вызов для этого сбоя, так как это не настоящий сбой времени выполнения, а то, что разработчик может наблюдать, пытаясь заставить сеть работать на делегате.

Советы по оптимизации

Оптимизация под мобильные устройства

Некоторые тривиальные операции с центральным процессором могут дорого обходиться графическому процессору на мобильных устройствах. Операции переформовать особенно дорого для запуска, в том числе BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH , и так далее. Вам следует внимательно изучить использование операций изменения формы и учесть, что они могли применяться только для исследования данных или для ранних итераций вашей модели. Их удаление может значительно повысить производительность.

На графическом процессоре тензорные данные разделяются на 4 канала. Таким образом, вычисление на тензора формы [B,H,W,5] будет выполнять примерно то же самое на тензора формы [B,H,W,8] , но значительно хуже , чем [B,H,W,4] . В этом смысле, если оборудование камеры поддерживает кадры изображения в RGBA, подача этого 4-канального входа будет значительно быстрее, поскольку можно избежать копирования в память (из 3-канального RGB в 4-канальный RGBX).

Для достижения наилучшей производительности вам следует подумать о переобучении классификатора с помощью сетевой архитектуры, оптимизированной для мобильных устройств. Оптимизация логических выводов на устройстве может значительно снизить задержку и энергопотребление за счет использования преимуществ мобильного оборудования.

Сокращение времени инициализации с помощью сериализации

Функция делегирования графического процессора позволяет загружать из предварительно скомпилированного кода ядра и сериализованные и сохраненные на диске данные модели из предыдущих запусков. Такой подход позволяет избежать повторной компиляции и сокращает время запуска до 90%. Инструкции о том , как применять сериализации в проект, см GPU Делегирование сериализации .