Delegasi GPU TensorFlow Lite

TensorFlow Lite mendukung beberapa akselerator perangkat keras. Dokumen ini menjelaskan cara menggunakan backend GPU menggunakan API delegasi TensorFlow Lite di Android dan iOS.

GPU dirancang untuk memiliki throughput tinggi untuk beban kerja yang dapat diparalelkan secara masif. Dengan demikian, mereka sangat cocok untuk jaring saraf dalam, yang terdiri dari sejumlah besar operator, masing-masing bekerja pada beberapa tensor input yang dapat dengan mudah dibagi menjadi beban kerja yang lebih kecil dan dilakukan secara paralel, biasanya menghasilkan latensi yang lebih rendah. Dalam skenario terbaik, inferensi pada GPU sekarang dapat berjalan cukup cepat untuk aplikasi waktu nyata yang sebelumnya tidak tersedia.

Tidak seperti CPU, GPU menghitung dengan angka floating point 16-bit atau 32-bit dan tidak memerlukan kuantisasi untuk kinerja yang optimal. Delegasi tidak menerima model terkuantisasi 8-bit, tetapi perhitungan akan dilakukan dalam angka floating point. Lihat dokumentasi lanjutan untuk detailnya.

Manfaat lain dengan inferensi GPU adalah efisiensi dayanya. GPU melakukan komputasi dengan cara yang sangat efisien dan optimal, sehingga mereka mengkonsumsi lebih sedikit daya dan menghasilkan lebih sedikit panas daripada saat tugas yang sama dijalankan pada CPU.

Tutorial aplikasi demo

Cara termudah untuk mencoba delegasi GPU adalah dengan mengikuti tutorial di bawah ini, yang melalui pembuatan aplikasi demo klasifikasi kami dengan dukungan GPU. Kode GPU hanya biner untuk saat ini; itu akan segera menjadi sumber terbuka. Setelah Anda memahami cara membuat demo kami berfungsi, Anda dapat mencobanya pada model kustom Anda sendiri.

Android (dengan Android Studio)

Untuk tutorial langkah demi langkah, tonton video Delegate GPU untuk Android .

Langkah 1. Kloning kode sumber TensorFlow dan buka di Android Studio

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

Langkah 2. Edit app/build.gradle untuk menggunakan GPU AAR malam

Tambahkan paket tensorflow-lite-gpu di samping paket tensorflow-lite yang ada di blok dependencies yang ada.

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

Langkah 3. Bangun dan jalankan

Jalankan → Jalankan 'aplikasi'. Saat Anda menjalankan aplikasi, Anda akan melihat tombol untuk mengaktifkan GPU. Ubah dari model terkuantisasi ke model float lalu klik GPU untuk berjalan di GPU.

menjalankan demo gpu android dan beralih ke gpu

iOS (dengan XCode)

Untuk tutorial langkah demi langkah, tonton video Delegasi GPU untuk iOS .

Langkah 1. Dapatkan kode sumber demo dan pastikan itu dikompilasi.

Ikuti tutorial Aplikasi Demo iOS kami. Ini akan membawa Anda ke titik di mana demo kamera iOS yang tidak dimodifikasi berfungsi di ponsel Anda.

Langkah 2. Ubah Podfile untuk menggunakan TensorFlow Lite GPU CocoaPod

Dari rilis 2.3.0, secara default delegasi GPU dikeluarkan dari pod untuk mengurangi ukuran biner. Anda dapat memasukkannya dengan menentukan subspec. Untuk pod TensorFlowLiteSwift :

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

ATAU

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

Anda dapat melakukan hal yang sama untuk TensorFlowLiteObjC atau TensorFlowLitC jika Anda ingin menggunakan Objective-C (dari rilis 2.4.0) atau C API.

Sebelum rilis 2.3.0

Hingga TensorFlow Lite 2.0.0

Kami telah membangun CocoaPod biner yang menyertakan delegasi GPU. Untuk mengalihkan proyek agar menggunakannya, ubah file `tensorflow/tensorflow/lite/examples/ios/camera/Podfile` untuk menggunakan pod `TensorFlowLiteGpuExperimental` alih-alih `TensorFlowLite`.


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

Hingga TensorFlow Lite 2.2.0

Dari TensorFlow Lite 2.1.0 hingga 2.2.0, delegasi GPU disertakan dalam pod `TensorFlowLiteC`. Anda dapat memilih antara `TensorFlowLiteC` dan `TensorFlowLiteSwift` tergantung pada bahasanya.

Langkah 3. Aktifkan delegasi GPU

Untuk mengaktifkan kode yang akan menggunakan delegasi GPU, Anda perlu mengubah TFLITE_USE_GPU_DELEGATE dari 0 menjadi 1 di CameraExampleViewController.h .

#define TFLITE_USE_GPU_DELEGATE 1

Langkah 4. Bangun dan jalankan aplikasi demo

Setelah mengikuti langkah sebelumnya, Anda seharusnya dapat menjalankan aplikasi.

Langkah 5. Mode rilis

Sementara di Langkah 4 Anda menjalankan dalam mode debug, untuk mendapatkan kinerja yang lebih baik, Anda harus mengubah ke build rilis dengan pengaturan Metal optimal yang sesuai. Secara khusus, Untuk mengedit pengaturan ini, buka Product > Scheme > Edit Scheme... . Pilih Run . Pada tab Info , ubah Build Configuration , dari Debug ke Release , hapus centang Debug executable .

mengatur rilis

Kemudian klik tab Options dan ubah GPU Frame Capture menjadi Disabled dan Metal API Validation menjadi Disabled .

menyiapkan opsi logam

Terakhir pastikan untuk memilih Release-only builds on 64-bit architecture. Di bawah Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings set Build Active Architecture Only > Release to Yes.

menyiapkan opsi rilis

Mencoba delegasi GPU pada model Anda sendiri

Android

Ada dua cara untuk memanggil akselerasi model bergantung pada apakah Anda menggunakan Android Studio ML Model Binding atau TensorFlow Lite Interpreter.

Penerjemah TensorFlow Lite

Lihat demo untuk melihat cara menambahkan delegasi. Di aplikasi Anda, tambahkan AAR seperti di atas, impor modul org.tensorflow.lite.gpu.GpuDelegate , dan gunakan fungsi addDelegate untuk mendaftarkan delegasi GPU ke interpreter:

Kotlin

    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)
      

Jawa

    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

Cepat

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

Objective-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 (Sampai 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.
```

Kami tidak menyediakan panggilan balik untuk kegagalan ini, karena ini bukan kegagalan run-time yang sebenarnya, tetapi sesuatu yang dapat diamati oleh pengembang saat mencoba menjalankan jaringan pada delegasi.

Kiat untuk pengoptimalan

Mengoptimalkan untuk perangkat seluler

Beberapa operasi yang sepele pada CPU mungkin memiliki biaya tinggi untuk GPU pada perangkat seluler. Operasi pembentukan ulang sangat mahal untuk dijalankan, termasuk BATCH_TO_SPACE , SPACE_TO_BATCH , SPACE_TO_DEPTH , dan seterusnya. Anda harus memeriksa dengan cermat penggunaan operasi pembentukan kembali, dan mempertimbangkan bahwa mungkin telah diterapkan hanya untuk menjelajahi data atau untuk iterasi awal model Anda. Menghapusnya dapat meningkatkan kinerja secara signifikan.

Pada GPU, data tensor dipotong menjadi 4 saluran. Dengan demikian, komputasi pada tensor bentuk [B,H,W,5] akan bekerja hampir sama pada tensor bentuk [B,H,W,8] tetapi secara signifikan lebih buruk daripada [B,H,W,4] . Dalam hal ini, jika perangkat keras kamera mendukung bingkai gambar dalam RGBA, mengumpankan input 4 saluran tersebut secara signifikan lebih cepat karena salinan memori (dari RGB 3 saluran ke RGBX 4 saluran) dapat dihindari.

Untuk kinerja terbaik, Anda harus mempertimbangkan untuk melatih ulang pengklasifikasi dengan arsitektur jaringan yang dioptimalkan untuk seluler. Pengoptimalan untuk inferensi pada perangkat dapat secara dramatis mengurangi latensi dan konsumsi daya dengan memanfaatkan fitur perangkat keras seluler.

Mengurangi waktu inisialisasi dengan serialisasi

Fitur delegasi GPU memungkinkan Anda untuk memuat dari kode kernel yang telah dikompilasi sebelumnya dan data model yang diserialisasikan dan disimpan pada disk dari proses sebelumnya. Pendekatan ini menghindari kompilasi ulang dan mengurangi waktu startup hingga 90%. Untuk petunjuk tentang cara menerapkan serialisasi ke proyek Anda, lihat Serialisasi Delegasi GPU .