השימוש ביחידות עיבוד גרפיות (GPU) להפעלת מודלים של למידת מכונה (ML) יכול לשפר משמעותית את ביצועי המודל ואת חוויית המשתמש באפליקציות שתומכות ב-ML. TensorFlow Lite מאפשר להשתמש במעבדי GPU ובמעבדים מיוחדים אחרים באמצעות מנהלי התקן של חומרה שנקראים נציגים. הפעלת השימוש ב-GPU באפליקציות TensorFlow Lite ML יכולה לספק את היתרונות הבאים:
- מהירות – יחידות GPU מותאמות לתפוקה גבוהה של עומסי עבודה מקבילים מאוד. בזכות העיצוב הזה הם מתאימים במיוחד לרשתות נוירונים עמוקות, שכוללות מספר גדול של אופרטורים, שכל אחד מהם עובד על גופי קלט שניתן לעבד במקביל, מה שמוביל בדרך כלל לזמן אחזור קצר יותר. בתרחיש הטוב ביותר, הפעלת המודל ב-GPU עשויה לפעול מהר מספיק כדי להפעיל אפליקציות בזמן אמת שלא היו אפשריות קודם לכן.
- יעילות בצריכת חשמל – יחידות GPU מבצעות חישובי למידת מכונה (ML) באופן יעיל ומשופר, בדרך כלל צורכות פחות חשמל ומפיקות פחות חום מאשר אותה משימה שפועלת במעבדים.
במסמך הזה מפורטת סקירה כללית על התמיכה במעבדי GPU ב-TensorFlow Lite, ועל שימושים מתקדמים במעבדי GPU. למידע ספציפי יותר על הטמעת תמיכה ב-GPU בפלטפורמות ספציפיות, כדאי לעיין במדריכים הבאים:
תמיכה בפעולות GPU ML
יש כמה מגבלות על הפעולות ש-TensorFlow Lite GPU יכול להאיץ, או פעולות, על ידי נציג של TensorFlow Lite GPU. בעל הגישה תומך בפעולות הבאות ברמת צף של 16 ביט ו-32 ביט:
ADD
AVERAGE_POOL_2D
CONCATENATION
CONV_2D
DEPTHWISE_CONV_2D v1-2
EXP
FULLY_CONNECTED
LOGICAL_AND
LOGISTIC
LSTM v2 (Basic LSTM only)
MAX_POOL_2D
MAXIMUM
MINIMUM
MUL
PAD
PRELU
RELU
RELU6
RESHAPE
RESIZE_BILINEAR v1-3
SOFTMAX
STRIDED_SLICE
SUB
TRANSPOSE_CONV
כברירת מחדל, כל הפעולות נתמכות רק בגרסה 1. הפעלת התמיכה לקונטיזציה מפעילה את הגרסאות המתאימות, לדוגמה, ADD v2.
פתרון בעיות בתמיכה ב-GPU
אם בעלי הגישה ל-GPU לא תומכים בחלק מהפעולות, ה-framework יריץ רק חלק מהתרשים ב-GPU ואת החלק הנותר במעבד (CPU). בגלל העלות הגבוהה של סנכרון בין המעבד (CPU) לבין ה-GPU, מצב ביצוע מפוצל כזה בדרך כלל מוביל לביצועים איטיים יותר מאשר כאשר כל הרשת פועלת על המעבד (CPU) בלבד. במקרה כזה, האפליקציה יוצרת אזהרה, למשל:
WARNING: op code #42 cannot be handled by this delegate.
אין קריאה חוזרת (callback) לכשלים מהסוג הזה כי לא מדובר בכשל בזמן הריצה בפועל. כשבודקים את הביצוע של המודל עם נציג GPU, חשוב לשים לב לאזהרות האלה. מספר גדול של אזהרות יכול להצביע על כך שהמודל שלכם לא מתאים בצורה הטובה ביותר להאצה של GPU, וייתכן שיידרש ארגון מחדש של המודל.
מודלים לדוגמה
הדוגמאות הבאות מיועדות לנצל את ההאצה של ה-GPU באמצעות TensorFlow Lite, וניתנות לעיון ולבדיקה:
- MobileNet v1 (224x224) (סיווג תמונות) – מודל לסיווג תמונות שמיועד לאפליקציות לניידים ולאפליקציות לראייה מוטמעת. (model)
- פילוח של DeepLab (257x257) – מודל לפילוח תמונות שמקצה תוויות סמנטיות, כמו כלב, חתול או מכונית, לכל פיקסל בתמונת הקלט. (model)
- זיהוי אובייקטים מסוג MobileNet SSD – מודל לסיווג תמונות שמזהה מספר אובייקטים עם תיבות תוחמות. (model)
- PoseNet להערכת תנוחה – מודל ראייה שמעריך את העמדות של אנשים בתמונה או בסרטון. (model)
אופטימיזציה ל-GPU
אפשר להיעזר בשיטות הבאות כדי לשפר את הביצועים כשמפעילים מודלים בחומרת GPU באמצעות נציג של TensorFlow Lite GPU:
ביצוע מחדש של פעולות – פעולות מסוימות שמבוצעות במהירות במעבד (CPU) עשויות להיות בעלות גבוהה ל-GPU במכשירים ניידים. פעולות שינוי גודל יקרות במיוחד, כולל
BATCH_TO_SPACE
,SPACE_TO_BATCH
,SPACE_TO_DEPTH
וכן הלאה. יש לבחון בקפידה את השימוש בפעולות שינוי צורה, ולשקול שייתכן שהשתמשתם רק לצורך בחינת נתונים או באיטרציות מוקדמות של המודל. הסרתן יכולה לשפר משמעותית את הביצועים.ערוצי נתונים של תמונות – ב-GPU, נתוני tensor פרוסים ל-4 ערוצים, ולכן חישוב של טנזור בצורה
[B,H,W,5]
פועל בערך באותו אופן על טנזור בצורה[B,H,W,8]
, אבל גרוע משמעותית מ-[B,H,W,4]
. אם חומרת המצלמה שבה אתם משתמשים תומכת בפריימים של תמונות ב-RGBA, ההזנה של הקלט בן 4 הערוצים מהירה יותר משמעותית, כי הוא חוסך העתקת זיכרון מ-RGB ב-3 ערוצים ל-RGBX ב-4 ערוצים.מודלים מותאמים לניידים – על מנת ליהנות מהביצועים הטובים ביותר, כדאי לאמן מחדש את המסווג באמצעות ארכיטקטורת רשת שמותאמת לניידים. אופטימיזציה של הסקת מסקנות במכשיר יכולה להפחית משמעותית את זמן האחזור ואת צריכת החשמל, כי הוא עוזר לנצל את היתרונות של תכונות חומרה לנייד.
תמיכה מתקדמת ב-GPU
אפשר להשתמש בטכניקות מתקדמות נוספות בעיבוד GPU כדי לשפר עוד יותר את הביצועים של המודלים, כולל קוונטיזציה וסריאליזציה. בקטעים הבאים נרחיב על השיטות האלה.
שימוש במודלים קוונטיים
בקטע הזה מוסבר איך להעניק גישה ל-GPU מאיצים מודלים קוונטיים ב-8 ביט, כולל:
- מודלים שהוכשרו לכך באמצעות הדרכה מבוססת-קביעת כמות
- קוונטיזציה של טווח דינמי אחרי אימון
- קוונטיזציה של מספרים שלמים אחרי אימון
כדי לבצע אופטימיזציה של הביצועים, צריך להשתמש במודלים שיש בהם גם גורמי קלט בנקודה צפה (floating-point) וגם טנזורי פלט.
איך זה עובד?
מכיוון שהקצה העורפי של ה-GPU תומך רק בביצוע נקודה צפה (floating-point), אנחנו מריצים מודלים מכניים על ידי הענקת 'תצוגת נקודה צפה' של המודל המקורי. ברמה גבוהה, זה כולל את השלבים הבאים:
ערכי tensor קבועים (כמו משקולות או הטיות) מבוטלים כשהם עוברים לזיכרון ה-GPU. הפעולה הזו מתבצעת כשבעלי הגישה מופעלים ל-TensorFlow Lite.
שיטות קלט ופלט לתוכנית ה-GPU, אם מתבצע קוונטיזציה של 8 ביט, הן מוסרות ומכמתות (בהתאמה) לכל הסקת מסקנות. הפעולה הזו מתבצעת במעבד (CPU) באמצעות הליבות שעברו אופטימיזציה של TensorFlow Lite.
מוסיפים סימולטורים של קוונטיזציה בין פעולות כדי לחקות התנהגות קוונטית. הגישה הזו נחוצה למודלים שבהם פעולות התפעול מצפות שההפעלות יתאימו לגבולות שנלמדו במהלך הקוונטיזציה.
למידע על הפעלת התכונה הזו עם מואצל GPU:
- שימוש במודלים מכווננים עם GPU ב-Android
- שימוש במודלים מכווננים עם GPU ב-iOS
קיצור זמן האתחול עם סריאליזציה
תכונת ההאצלה של GPU מאפשרת לטעון מקוד הליבה ומנתוני המודל שעברו הידור מראש, שעברו סריאליזציה ונשמרים בדיסק מהפעלות קודמות. הגישה הזו מונעת הידור מחדש ועשויה לקצר את זמן ההפעלה בשיעור של עד 90%. אפשר להשיג את השיפור הזה באמצעות החלפת מקום הדיסק לחיסכון בזמן. אפשר להפעיל את התכונה הזו באמצעות כמה אפשרויות תצורה, כפי שמוצג בדוגמאות הקוד הבאות:
C++
TfLiteGpuDelegateOptionsV2 options = TfLiteGpuDelegateOptionsV2Default(); options.experimental_flags |= TFLITE_GPU_EXPERIMENTAL_FLAGS_ENABLE_SERIALIZATION; options.serialization_dir = kTmpDir; options.model_token = kModelToken; auto* delegate = TfLiteGpuDelegateV2Create(options); if (interpreter->ModifyGraphWithDelegate(delegate) != kTfLiteOk) return false;
Java
GpuDelegate delegate = new GpuDelegate( new GpuDelegate.Options().setSerializationParams( /* serializationDir= */ serializationDir, /* modelToken= */ modelToken)); Interpreter.Options options = (new Interpreter.Options()).addDelegate(delegate);
כשמשתמשים בתכונה סריאליזציה, צריך לוודא שהקוד עומד בכללי ההטמעה הבאים:
- שמירת נתוני העריכה בסדרה שלא נגישה לאפליקציות אחרות. במכשירי Android, מקישים על הסמל
getCodeCacheDir()
שמפנה למיקום פרטי באפליקציה הנוכחית. - אסימון המודל חייב להיות ייחודי למכשיר של הדגם הספציפי. אפשר
לחשב אסימון מודל על ידי יצירת טביעת אצבע מנתוני המודל באמצעות ספריות כמו
farmhash::Fingerprint64
.