בעלי גישה ל-GPU ב-TensorFlow Lite

השימוש ביחידות עיבוד גרפיות (GPU) להפעלת מודלים של למידת מכונה (ML) יכול לשפר משמעותית את ביצועי המודל ואת חוויית המשתמש באפליקציות שתומכות בלמידת מכונה. TensorFlow Lite מאפשר להשתמש במעבדי GPU ובמעבדים מיוחדים אחרים באמצעות מנהל התקן חומרה שנקרא נציגים. הפעלת השימוש במעבדי GPU באפליקציות למידת מכונה TensorFlow Lite יכולה לספק את היתרונות הבאים:

  • מהירות – מעבדי ה-GPU מתאימים לתפוקה גבוהה של עומסי עבודה מקבילים ומעצימים. בזכות התכנון הזה, הן מתאימות במיוחד לרשתות נוירונים עמוקות, שכוללות מספר עצום של אופרטורים, שכל אחד מהם עובד על מזיני קלט שאפשר לעבד במקביל, ולכן בדרך כלל התוצאה היא זמן אחזור קצר. בתרחיש הטוב ביותר, הרצת המודל ב-GPU עשויה לרוץ מהר מספיק כדי לאפשר אפליקציות בזמן אמת שלא היו אפשריות קודם לכן.
  • חיסכון בצריכת החשמל – מעבדי GPU מבצעים חישובים של למידת מכונה באופן יעיל ואופטימלי, ולרוב צורכים פחות חשמל ומפיקים פחות חום בהשוואה לאותה משימה שפועלת במעבדי CPU.

במסמך הזה מפורטת סקירה כללית על התמיכה במעבדי GPU ב-TensorFlow Lite, ושימושים מתקדמים מסוימים במעבדי GPU. למידע ספציפי יותר על הטמעת תמיכה ב-GPU בפלטפורמות ספציפיות, עיינו במדריכים הבאים:

תמיכה בפעולות של GPU ML

יש כמה מגבלות על הפעולות שמשתמשים ב-TensorFlow ML, או פעולות, יכולים להאיץ. בעל הגישה תומך בפעולות הבאות ברמת דיוק של ציפה של 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) ל-GPU, מצב ביצוע מפוצל כמו זה בדרך כלל גורם לביצועים איטיים יותר מאשר כשהרשת כולה פועלת במעבד (CPU) בלבד. במקרה כזה, האפליקציה יוצרת אזהרה, למשל:

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

אין קריאה חוזרת לכשלים מהסוג הזה, כי זה לא כשל בזמן הריצה בפועל. כשבודקים את הביצוע של המודל באמצעות מקבל הגישה ל-GPU, חשוב לקבל התראה על האזהרות האלה. מספר גבוה של האזהרות האלה יכול להצביע על כך שהמודל לא מתאים לשימוש ביותר לצורך האצת GPU, ויכול להיות שיידרש ארגון מחדש (Refactoring) של המודל.

מודלים לדוגמה

המודלים הבאים לדוגמה נועדו לנצל את האצת ה-GPU עםTensorFlow Lite, והם ניתנים לעיון ולבדיקה:

אופטימיזציה למעבדי GPU

הטכניקות הבאות יכולות לעזור לכם לשפר את הביצועים כשמריצים מודלים בחומרת GPU באמצעות מקבל הגישה ל-GPU של TensorFlow Lite:

  • שינוי פעולות – פעולות מסוימות, שמבוצעות במהירות במעבד (CPU), עשויות להיות בעלות גבוהה על ה-GPU במכשירים ניידים. פעולות של עיצוב מחדש יקרות במיוחד, כולל BATCH_TO_SPACE, SPACE_TO_BATCH, SPACE_TO_DEPTH וכן הלאה. צריך לבחון היטב את השימוש בפעולות עיצוב מחדש, ולשקול אם הוא יושם רק לצורך גילוי נתונים או איטרציות מוקדמות של המודל. הסרתן יכולה לשפר משמעותית את הביצועים.

  • ערוצי נתונים של תמונות – ב-GPU, נתוני הטנזור מחולקים ל-4 ערוצים, כך שהחישוב של טנזור עם הצורה [B,H,W,5] מניב ביצועים זהים ב-Tensor בצורת [B,H,W,8], אבל פחות משמעותית מ-[B,H,W,4]. אם חומרת המצלמה שבה אתם משתמשים תומכת בפריימים של תמונות ב-RGBA, הזנת הקלט ב-4 הערוצים מהירה יותר בצורה משמעותית כי נמנעת מהעתקת זיכרון מ-RGB בשלוש ערוצים ל-RGBX ב-4 ערוצים.

  • מודלים מותאמים לניידים – לקבלת הביצועים הטובים ביותר, מומלץ לאמן מחדש את המסווג באמצעות ארכיטקטורת רשת שמותאמת לניידים. אופטימיזציה של הסקת המסקנות במכשיר יכולה לצמצם משמעותית את זמן האחזור ואת צריכת החשמל, על ידי ניצול של תכונות החומרה בנייד.

תמיכה מתקדמת ב-GPU

תוכלו להשתמש בשיטות מתקדמות נוספות עם עיבוד GPU כדי לשפר את הביצועים של המודלים שלכם, כולל כימות ויצירה בהמשכיות. בקטעים הבאים נרחיב על הטכניקות האלה.

שימוש במודלים כמותיים

בקטע הזה מוסבר איך הקצאת הגישה ל-GPU מאיצה מודלים כמותיים של 8 ביט, כולל הדברים הבאים:

כדי לשפר את הביצועים, כדאי להשתמש במודלים שיש להם גם רכיבי קלט מסוג נקודה צפה וגם פלט.

איך זה עובד?

מכיוון שהקצה העורפי של ה-GPU תומך רק בהפעלה בנקודה צפה (floating-point), אנחנו מפעילים מודלים כמותיים על ידי יצירת 'תצוגה נקודה צפה (floating-point)' של המודל המקורי. ברמה הכללית, התהליך כולל את השלבים הבאים:

  • כמות מסוימת של רכיבי Tensors קבועים (כמו משקולות/הטיות) מוסרת מהזיכרון פעם אחת בזיכרון ה-GPU. הפעולה הזו מתבצעת כשמקבל הגישה מופעל ב-TensorFlow Lite.

  • קלט ופלט לתוכנת ה-GPU, אם נעשה בהם קומנציה ב-8 ביט, הם יוסרו מהכמות וכאלה שהם מכוסים (בהתאמה) לכל מסקנות. הפעולה הזו מתבצעת במעבד (CPU) באמצעות הליבות שעברו אופטימיזציה של TensorFlow Lite.

  • מוסיפים סימולטורים של כמויות בין פעולות כדי לחקות התנהגות כמותית. הגישה הזו נחוצה למודלים שבהם הפעולות מצפות שההפעלות יהיו בהתאם לגבולות שנלמדו במהלך הקוונטיזציה.

למידע נוסף על הפעלת התכונה הזו באמצעות מקבל הגישה ל-GPU:

צמצום זמן האתחול באמצעות סריאליזציה

התכונה 'הענקת גישה ל-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.