Delegaci TensorFlow Lite

Wstęp

Delegaty umożliwiają sprzętową akcelerację modeli TensorFlow Lite poprzez wykorzystanie akceleratorów zainstalowanych na urządzeniu, takich jak procesor graficzny i procesor sygnału cyfrowego (DSP) .

Domyślnie TensorFlow Lite wykorzystuje jądra procesora zoptymalizowane pod kątem zestawu instrukcji ARM Neon . Jednak procesor jest procesorem wielofunkcyjnym, który niekoniecznie jest zoptymalizowany pod kątem ciężkiej arytmetyki zwykle spotykanej w modelach uczenia maszynowego (na przykład matematyki macierzowej związanej ze splotem i gęstymi warstwami).

Z drugiej strony większość nowoczesnych telefonów komórkowych zawiera chipy, które lepiej radzą sobie z tak ciężkimi operacjami. Wykorzystanie ich do operacji sieci neuronowych zapewnia ogromne korzyści w zakresie opóźnień i wydajności energetycznej. Na przykład procesory graficzne mogą zapewnić nawet 5-krotne przyspieszenie opóźnienia, podczas gdy w naszych eksperymentach Qualcomm® Hexagon DSP wykazało, że zmniejsza zużycie energii aż do 75%.

Każdy z tych akceleratorów ma powiązane interfejsy API, które umożliwiają niestandardowe obliczenia, takie jak OpenCL lub OpenGL ES dla mobilnych procesorów graficznych i Qualcomm® Hexagon SDK dla DSP. Zwykle trzeba napisać dużo niestandardowego kodu, aby uruchomić sieć neuronową za pośrednictwem tych interfejsów. Sprawa staje się jeszcze bardziej skomplikowana, gdy weźmie się pod uwagę, że każdy akcelerator ma swoje zalety i wady i nie jest w stanie wykonać każdej operacji w sieci neuronowej. Interfejs API Delegate TensorFlow Lite rozwiązuje ten problem, działając jako pomost pomiędzy środowiskiem wykonawczym TFLite a interfejsami API niższego poziomu.

środowisko uruchomieniowe z delegatami

Wybór delegata

TensorFlow Lite obsługuje wiele delegatów, z których każdy jest zoptymalizowany pod kątem określonych platform i określonych typów modeli. Zwykle do Twojego przypadku użycia będzie można zastosować wielu delegatów, w zależności od dwóch głównych kryteriów: platformy (Android czy iOS?), na którą kierujesz, oraz typu modelu (zmiennoprzecinkowego czy kwantowego?), który próbujesz przyspieszyć .

Delegaci według Platformy

Wieloplatformowy (Android i iOS)

  • Delegat GPU — delegata GPU można używać zarówno w systemie Android, jak i iOS. Jest zoptymalizowany do obsługi 32-bitowych i 16-bitowych modeli typu float, w których dostępny jest procesor graficzny. Obsługuje również 8-bitowe modele kwantyzowane i zapewnia wydajność procesora graficznego na poziomie ich wersji float. Aby uzyskać szczegółowe informacje na temat delegata GPU, zobacz TensorFlow Lite na GPU . Aby zapoznać się z samouczkami krok po kroku dotyczącymi korzystania z delegata procesora GPU w systemach Android i iOS, zobacz Samouczek delegowania procesora GPU TensorFlow Lite .

Android

  • Delegat NNAPI dla nowszych urządzeń z Androidem - Delegat NNAPI może być używany do przyspieszania modeli na urządzeniach z Androidem z dostępnym procesorem graficznym, DSP i/lub NPU. Jest dostępny w systemie Android 8.1 (API 27+) lub nowszym. Aby zapoznać się z omówieniem delegata NNAPI, instrukcjami krok po kroku i najlepszymi praktykami, zobacz Delegat TensorFlow Lite NNAPI .
  • Delegat Hexagon dla starszych urządzeń z Androidem - Delegat Hexagon może być używany do przyspieszania modeli na urządzeniach z Androidem z Qualcomm Hexagon DSP. Można go używać na urządzeniach ze starszymi wersjami Androida, które nie obsługują NNAPI. Aby uzyskać więcej informacji, zobacz delegata TensorFlow Lite Hexagon .

iOS

  • Delegat Core ML dla nowszych telefonów iPhone i iPadów — w przypadku nowszych telefonów iPhone i iPadów, na których dostępny jest silnik Neural Engine, można użyć delegowania Core ML w celu przyspieszenia wnioskowania dla 32-bitowych lub 16-bitowych modeli zmiennoprzecinkowych. Neural Engine jest dostępny na urządzeniach mobilnych Apple z procesorem A12 SoC lub nowszym. Aby zapoznać się z omówieniem delegata Core ML i instrukcjami krok po kroku, zobacz Delegat TensorFlow Lite Core ML .

Delegaci według typu modelu

Każdy akcelerator jest projektowany z myślą o określonej szerokości bitowej danych. Jeśli udostępnisz delegatowi model zmiennoprzecinkowy, który obsługuje tylko 8-bitowe operacje kwantyzowane (takie jak delegat Hexagon ), odrzuci on wszystkie jego operacje i model będzie działał wyłącznie na procesorze. Aby uniknąć takich niespodzianek, poniższa tabela zawiera przegląd obsługi delegatów w zależności od typu modelu:

Typ modelu GPU NNAPI Sześciokąt CoreML
Liczba zmiennoprzecinkowa (32 bity) Tak Tak NIE Tak
Kwantyzacja typu float16 po treningu Tak NIE NIE Tak
Kwantyzacja zakresu dynamicznego po treningu Tak Tak NIE NIE
Kwantyzacja liczb całkowitych po treningu Tak Tak Tak NIE
Szkolenie uwzględniające kwantyzację Tak Tak Tak NIE

Sprawdzanie wydajności

Informacje zawarte w tej sekcji służą jako ogólne wytyczne dotyczące tworzenia krótkiej listy delegatów, którzy mogliby ulepszyć Twoją aplikację. Należy jednak pamiętać, że każdy delegat ma wstępnie zdefiniowany zestaw obsługiwanych operacji i może działać inaczej w zależności od modelu i urządzenia; na przykład delegat NNAPI może zdecydować się na użycie procesora Edge-TPU firmy Google na telefonie Pixel podczas korzystania z procesora DSP na innym urządzeniu. Dlatego zwykle zaleca się przeprowadzenie testów porównawczych, aby ocenić, jak przydatny jest delegat dla Twoich potrzeb. Pomaga to również uzasadnić wzrost rozmiaru pliku binarnego związany z dołączeniem delegata do środowiska wykonawczego TensorFlow Lite.

TensorFlow Lite posiada rozbudowane narzędzia do oceny wydajności i dokładności, które mogą zapewnić programistom pewność korzystania z delegatów w swoich aplikacjach. Narzędzia te zostały omówione w następnej sekcji.

Narzędzia ewaluacji

Opóźnienie i ślad pamięci

Narzędzie testowe TensorFlow Lite może być używane z odpowiednimi parametrami do szacowania wydajności modelu, w tym średniego opóźnienia wnioskowania, narzutu inicjalizacji, zużycia pamięci itp. To narzędzie obsługuje wiele flag, aby znaleźć najlepszą konfigurację delegowania dla Twojego modelu. Na przykład --gpu_backend=gl można określić za pomocą --use_gpu , aby zmierzyć wykonanie procesora graficznego w OpenGL. Pełna lista obsługiwanych parametrów delegatów jest zdefiniowana w szczegółowej dokumentacji .

Oto przykład uruchomienia modelu skwantowanego z procesorem graficznym za pośrednictwem adb :

adb shell /data/local/tmp/benchmark_model \
  --graph=/data/local/tmp/mobilenet_v1_224_quant.tflite \
  --use_gpu=true

Możesz pobrać gotową wersję tego narzędzia dla systemu Android, 64-bitową architekturę ARM tutaj ( więcej szczegółów ).

Dokładność i poprawność

Delegaci zazwyczaj wykonują obliczenia z inną precyzją niż ich odpowiedniki na procesorze. W rezultacie istnieje (zwykle niewielki) kompromis w zakresie dokładności związany z wykorzystaniem delegata do przyspieszania sprzętowego. Pamiętaj, że nie zawsze jest to prawdą; na przykład, ponieważ procesor graficzny wykorzystuje precyzję zmiennoprzecinkową do uruchamiania skwantowanych modeli, może nastąpić niewielka poprawa precyzji (np. <1% poprawy w pierwszej piątce w klasyfikacji obrazów ILSVRC).

TensorFlow Lite ma dwa typy narzędzi do pomiaru dokładności zachowania delegata dla danego modelu: oparte na zadaniach i niezależne od zadań . Wszystkie narzędzia opisane w tej sekcji obsługują zaawansowane parametry delegowania wykorzystywane przez narzędzie do analizy porównawczej z poprzedniej sekcji. Należy zauważyć, że poniższe podsekcje skupiają się na ocenie delegata (czy delegat wykonuje to samo co procesor?), a nie na ocenie modelu (czy sam model jest dobry do wykonania zadania?).

Ocena oparta na zadaniach

TensorFlow Lite posiada narzędzia do oceny poprawności dwóch zadań opartych na obrazach:

Gotowe pliki binarne tych narzędzi (Android, 64-bitowa architektura ARM) wraz z dokumentacją można znaleźć tutaj:

Poniższy przykład ilustruje ocenę klasyfikacji obrazu za pomocą NNAPI z wykorzystaniem Edge-TPU firmy Google na Pixelu 4:

adb shell /data/local/tmp/run_eval \
  --model_file=/data/local/tmp/mobilenet_quant_v1_224.tflite \
  --ground_truth_images_path=/data/local/tmp/ilsvrc_images \
  --ground_truth_labels=/data/local/tmp/ilsvrc_validation_labels.txt \
  --model_output_labels=/data/local/tmp/model_output_labels.txt \
  --output_file_path=/data/local/tmp/accuracy_output.txt \
  --num_images=0 # Run on all images. \
  --use_nnapi=true \
  --nnapi_accelerator_name=google-edgetpu

Oczekiwany wynik to lista metryk Top-K od 1 do 10:

Top-1 Accuracy: 0.733333
Top-2 Accuracy: 0.826667
Top-3 Accuracy: 0.856667
Top-4 Accuracy: 0.87
Top-5 Accuracy: 0.89
Top-6 Accuracy: 0.903333
Top-7 Accuracy: 0.906667
Top-8 Accuracy: 0.913333
Top-9 Accuracy: 0.92
Top-10 Accuracy: 0.923333

Ocena niezależna od zadania

W przypadku zadań, w przypadku których nie ma ustalonego narzędzia do oceny na urządzeniu lub jeśli eksperymentujesz z niestandardowymi modelami, TensorFlow Lite ma narzędzie Inference Diff . (Android, 64-bitowy plik binarny o architekturze binarnej ARM tutaj )

Inference Diff porównuje wykonanie TensorFlow Lite (pod względem opóźnienia i odchylenia wartości wyjściowej) w dwóch ustawieniach:

  • Wnioskowanie o jednowątkowym procesorze
  • Wnioskowanie zdefiniowane przez użytkownika - definiowane przez te parametry

W tym celu narzędzie generuje losowe dane Gaussa i przepuszcza je przez dwa interpretery TFLite - jeden obsługujący jednowątkowe jądra procesora, a drugi sparametryzowany na podstawie argumentów użytkownika.

Mierzy opóźnienie obu, a także bezwzględną różnicę między tensorami wyjściowymi z każdego interpretera, w przeliczeniu na element.

W przypadku modelu z pojedynczym tensorem wyjściowym wynik może wyglądać następująco:

Num evaluation runs: 50
Reference run latency: avg=84364.2(us), std_dev=12525(us)
Test run latency: avg=7281.64(us), std_dev=2089(us)
OutputDiff[0]: avg_error=1.96277e-05, std_dev=6.95767e-06

Oznacza to, że dla tensora wyjściowego o indeksie 0 elementy na wyjściu procesora różnią się od danych wyjściowych delegata średnio o 1.96e-05 .

Należy pamiętać, że interpretacja tych liczb wymaga głębszej wiedzy o modelu i znaczeniu każdego tensora wyjściowego. Jeśli jest to prosta regresja, która określa jakiś wynik lub osadzenie, różnica powinna być niewielka (w przeciwnym razie jest to błąd delegata). Jednak dane wyjściowe takie jak „klasa wykrywania” z modeli SSD są nieco trudniejsze do zinterpretowania. Na przykład użycie tego narzędzia może wykazać różnicę, ale nie musi to oznaczać, że z delegatem dzieje się naprawdę coś złego: rozważ dwie (fałszywe) klasy: „TV (ID: 10)”, „Monitor (ID:20)” — Jeśli delegat nieco mija się ze złotą prawdą i pokazuje monitor zamiast telewizora, różnica wyjściowa dla tego tensora może wynosić nawet 20-10 = 10.