TensorFlow לייט תומך מאיצי חומרה שונות. מסמך זה מתאר כיצד להשתמש ב-GPU backend באמצעות ממשקי API של נציג TensorFlow Lite ב-Android ו-iOS.
GPUs מתוכננים לקבל תפוקה גבוהה עבור עומסי עבודה הניתנים להקבלה מאסיבית. לפיכך, הם מתאימים היטב לרשתות עצביות עמוקות, המורכבות ממספר עצום של אופרטורים, כל אחד עובד על טנסור(ים) קלט שניתן לחלק בקלות לעומסי עבודה קטנים יותר ולבצע במקביל, מה שגורם בדרך כלל להשהייה נמוכה יותר. בתרחיש הטוב ביותר, ההסקה על ה-GPU עשויה לפעול במהירות מספיק עבור יישומי זמן אמת שלא היו זמינים בעבר.
בניגוד למעבדים, מעבדי GPU מחשבים עם מספרי נקודה צפה של 16 סיביות או 32 סיביות ואינם דורשים קוונטיזציה לביצועים מיטביים. הנציג אכן מקבל מודלים מכונטיים של 8 סיביות, אך החישוב יתבצע במספרי נקודה צפה. עיין בתיעוד המתקדם לפרטים.
יתרון נוסף בהסקת GPU הוא יעילות ההספק שלו. GPUs מבצעים את החישובים בצורה מאוד יעילה ומוטבת, כך שהם צורכים פחות חשמל ומייצרים פחות חום מאשר כאשר אותה משימה מופעלת על CPUs.
הדרכות לאפליקציה להדגמה
הדרך הקלה ביותר לנסות את נציג ה-GPU היא לעקוב אחר המדריכים שלהלן, שעוברים דרך בניית יישומי הדגמה לסיווג שלנו עם תמיכה ב-GPU. קוד ה-GPU הוא רק בינארי לעת עתה; זה יהיה בקוד פתוח בקרוב. ברגע שתבינו איך לגרום להדגמות שלנו לעבוד, תוכלו לנסות זאת בדגמים המותאמים אישית שלכם.
אנדרואיד (עם Android Studio)
לקבלת הדרכה צעד-אחר-צעד, לצפות האצלה GPU עבור אנדרואיד וידאו.
שלב 1. שכבו את קוד המקור של TensorFlow ופתחו אותו ב-Android Studio
git clone https://github.com/tensorflow/tensorflow
ערוך שלב 2. app/build.gradle
להשתמש AAR GPU הלילי
מוסיפים את 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 כדי להפעיל על ה-GPU.
iOS (עם XCode)
לקבלת הדרכה צעד-אחר-צעד, לצפות האצלה GPU עבור iOS וידאו.
שלב 1. קבל את קוד המקור של ההדגמה וודא שהוא מתחבר.
עקוב App הדגמת iOS שלנו ההדרכה . זה יביא אותך לנקודה שבה הדגמת מצלמת iOS ללא שינוי עובדת על הטלפון שלך.
שלב 2. שנה את ה-Podfile לשימוש ב- TensorFlow Lite GPU CocoaPod
מגרסה 2.3.0, כברירת מחדל, נציג GPU אינו נכלל מהפוד כדי להקטין את הגודל הבינארי. אתה יכול לכלול אותם על ידי ציון מפרט משנה. עבור 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
.
לבסוף, הקפד לבחור ב-Release-Only builds על ארכיטקטורת 64-bit. תחת Project navigator -> tflite_camera_example -> PROJECT -> tflite_camera_example -> Build Settings
להגדיר Build Active Architecture Only > Release
כ כן.
נסה את נציג ה-GPU בדגם שלך
דְמוּי אָדָם
ישנן שתי דרכים להפעיל האצת המודל תלוי אם אתה משתמש דגם ML סטודיו אנדרואיד כריכה או מתורגמן לייט TensorFlow.
מתורגמן 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)
Java
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 ... }
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 (עד 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.
```
לא סיפקנו התקשרות חוזרת עבור כשל זה, מכיוון שלא מדובר בכשל אמיתי בזמן ריצה, אלא משהו שהמפתח יכול לראות בזמן שהוא מנסה לגרום לרשת לפעול על הנציג.
טיפים לאופטימיזציה
אופטימיזציה עבור מכשירים ניידים
לחלק מהפעולות שהן טריוויאליות במעבד עשויות להיות עלות גבוהה עבור ה-GPU במכשירים ניידים. פעולות שנויות צורה הם יקרים במיוחד כדי לרוץ, כולל BATCH_TO_SPACE
, SPACE_TO_BATCH
, SPACE_TO_DEPTH
, וכן הלאה. עליך לבחון מקרוב את השימוש בפעולות צורה מחדש, ולשקול שאולי יושמו רק עבור חקירת נתונים או עבור איטרציות מוקדמות של המודל שלך. הסרתם יכולה לשפר משמעותית את הביצועים.
ב-GPU, נתוני טנזור מחולקים ל-4 ערוצים. לפיכך, חישוב על טנזור של הצורה [B,H,W,5]
יבצע בערך אותו על טנזור של הצורה [B,H,W,8]
אך גרוע משמעותית מאשר [B,H,W,4]
. במובן זה, אם חומרת המצלמה תומכת במסגרות תמונה ב-RGBA, ניתן להימנע מהזנה של קלט 4 ערוצים מהיר יותר באופן משמעותי, שכן עותק זיכרון (מ-3 ערוצים RGB ל-4 ערוצים RGBX).
לקבלת הביצועים הטובים ביותר, כדאי לשקול להכשיר מחדש את המסווג עם ארכיטקטורת רשת מותאמת לנייד. אופטימיזציה להסקת מסקנות במכשיר יכולה להפחית באופן דרמטי את זמן ההשהיה וצריכת החשמל על ידי ניצול תכונות החומרה לנייד.
צמצום זמן האתחול בעזרת סדרה
תכונת ה-GPU Delegate מאפשרת לטעון מקוד ליבה שהורכב מראש ונתוני מודל שנקבעו בסידרה ונשמרו בדיסק מהרצות קודמות. גישה זו מונעת קומפילציה מחדש ומפחיתה את זמן האתחול בעד 90%. לקבלת הוראות כיצד ליישם בהמשכים לפרויקט שלך, לראות בהמשכי האצלת GPU .