משתמשי LiteRT

האצלה מאפשרת שיפור מהירות באמצעות חומרה של מודלים של LiteRT על ידי מינוף של מאיצים במכשיר, כמו ה-GPU ומעבד אותות דיגיטלי (DSP).

כברירת מחדל, LiteRT משתמש בליבות מעבד שעברו אופטימיזציה לסט הפקודות ARM Neon. עם זאת, יחידת העיבוד המרכזית היא מעבד רב-תכליתי שלא בהכרח מותאם לאריתמטיקה הכבדה שנמצאת בדרך כלל במודלים של למידת מכונה (לדוגמה, המתמטיקה של מטריצות שקשורה לקונבולוציה ולשכבות צפופות).

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

לכל אחד מהמאיצים האלה יש ממשקי API משויכים שמאפשרים לבצע חישובים מותאמים אישית, כמו OpenCL או OpenGL ES ל-GPU בנייד. בדרך כלל, כדי להפעיל רשת עצבית דרך הממשקים האלה, צריך לכתוב הרבה קוד בהתאמה אישית. הדברים מסתבכים עוד יותר כשמביאים בחשבון שלכל מאיץ יש יתרונות וחסרונות, והוא לא יכול לבצע כל פעולה ברשת עצבית. ממשק ה-API של TensorFlow Lite Delegate פותר את הבעיה הזו בכך שהוא משמש כגשר בין זמן הריצה של TFLite לבין ממשקי ה-API ברמה הנמוכה יותר.

זמן ריצה עם נציגים

בחירת נציג

‫LiteRT תומך במספר נציגים, שכל אחד מהם מותאם לפלטפורמה או לפלטפורמות מסוימות ולסוגים מסוימים של מודלים. בדרך כלל יהיו כמה נציגים שמתאימים לתרחיש השימוש שלכם, בהתאם לשני קריטריונים עיקריים: הפלטפורמה (Android או iOS?) שאליה אתם מכוונים, וסוג המודל (נקודה צפה או כמותית?) שאתם מנסים להאיץ.

משתמשים שקיבלו הרשאה לפי פלטפורמה

פלטפורמות שונות (Android ו-iOS)

  • GPU delegate – אפשר להשתמש ב-GPU delegate גם ב-Android וגם ב-iOS. הוא מותאם להרצת מודלים מבוססי נקודה צפה של 32 ו-16 ביט, אם יש GPU זמין. הוא תומך גם במודלים שעברו קוונטיזציה של 8 ביט ומספק ביצועים של GPU שדומים לביצועים של הגרסאות שלהם עם נקודה צפה. פרטים על נציג ה-GPU זמינים במאמר בנושא LiteRT on GPU.

iOS

  • Core ML delegate לאייפונים ולאייפדים חדשים יותר – באייפונים ובאייפדים חדשים יותר שבהם Neural Engine זמין, אפשר להשתמש ב-Core ML delegate כדי להאיץ את ההסקה עבור מודלים של נקודה צפה של 32 ביט או 16 ביט. ‫Neural Engine זמין במכשירים ניידים של אפל עם מערכת על שבב (SoC) A12 או גרסה מתקדמת יותר. סקירה כללית של נציג Core ML והוראות מפורטות זמינות במאמר LiteRT Core ML delegate.

נציגים לפי סוג המודל

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

סוג המודל GPU CoreML
נקודה צפה (32 ביט) כן כן
כימות float16 אחרי האימון כן כן
Post-training dynamic range quantization כן לא
Post-training integer quantization כן לא
אימון עם התחשבות בקוונטיזציה כן לא

אימות הביצועים

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

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

כלים להערכה

חביון וזיכרון שבשימוש

אפשר להשתמש בכלי ההשוואה של LiteRT עם פרמטרים מתאימים כדי להעריך את ביצועי המודל, כולל זמן האחזור הממוצע של ההסקה, התקורה של האתחול, טביעת הזיכרון וכו'. הכלי הזה תומך בכמה דגלים כדי להבין מהי תצורת הנציג הטובה ביותר עבור המודל. לדוגמה, אפשר לציין את --gpu_backend=gl עם --use_gpu כדי למדוד את הביצוע של GPU עם OpenGL. הרשימה המלאה של פרמטרים נתמכים של נציגים מוגדרת בתיעוד המפורט.

דוגמה להרצה של מודל שעבר קוונטיזציה עם GPU באמצעות adb:

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

אפשר להוריד גרסה מוכנה מראש של הכלי הזה ל-Android, ארכיטקטורת ARM בגרסת 64 ביט כאן (פרטים נוספים).

דיוק ונכונות

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

ל-LiteRT יש שני סוגים של כלים למדידת רמת הדיוק של התנהגות נציג עבור מודל נתון: מבוסס-משימות ולא מבוסס-משימות. כל הכלים שמתוארים בקטע הזה תומכים בפרמטרים מתקדמים של הקצאת הרשאות שבהם נעשה שימוש בכלי ההשוואה לשוק מהקטע הקודם. שימו לב שהקטעים הבאים מתמקדים בהערכת ההקצאה (האם ההקצאה מתבצעת כמו במעבד?) ולא בהערכת המודל (האם המודל עצמו טוב למשימה?).

הערכה מבוססת-משימות

ל-LiteRT יש כלים להערכת נכונות בשתי משימות מבוססות-תמונה:

קובצי הפעלה בינאריים מוכנים מראש של הכלים האלה (Android, ארכיטקטורת ARM‏ 64 ביט), יחד עם תיעוד, זמינים כאן:

בדוגמה הבאה מוצגת הערכה של סיווג תמונות באמצעות GPU ב-Pixel 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_gpu=true

הפלט הצפוי הוא רשימה של מדדי Top-K מ-1 עד 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

הערכה ללא תלות במשימה

למשימות שאין להן כלי בדיקה מובנה במכשיר, או אם אתם מנסים מודלים בהתאמה אישית, ב-LiteRT יש את הכלי Inference Diff. ‫(Android, קובץ בינארי של ארכיטקטורת ARM בגרסת 64 ביט כאן)

הכלי Inference Diff משווה בין הביצועים של LiteRT (במונחים של זמן אחזור וסטייה של ערך הפלט) בשתי הגדרות:

  • הסקת מסקנות במעבד עם ליבה אחת
  • הסקת מסקנות שהוגדרה על ידי המשתמש – מוגדרת על ידי הפרמטרים האלה

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

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

עבור מודל עם טנסור פלט יחיד, הפלט יכול להיראות כך:

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

המשמעות היא שעבור טנסור הפלט באינדקס 0, האלמנטים מהפלט של ה-CPU שונים מהפלט של הנציג בממוצע של 1.96e-05.

הערה: כדי לפרש את המספרים האלה צריך ידע מעמיק יותר במודל ובמשמעות של כל טנסור פלט. אם מדובר ברגרסיה פשוטה שקובעת סוג מסוים של ניקוד או הטמעה, ההבדל צריך להיות קטן (אחרת מדובר בשגיאה בנציג). עם זאת, קשה יותר לפרש פלטים כמו 'סיווג הזיהוי' ממודלים של SSD. לדוגמה, יכול להיות שהכלי יציג הבדל, אבל זה לא אומר שיש בעיה אמיתית בנציג: נניח שיש שתי מחלקות (פיקטיביות): 'טלוויזיה (מזהה: 10)' ו'מסך (מזהה:20)'. אם נציג קצת חורג מהאמת המוחלטת ומציג מסך במקום טלוויזיה, יכול להיות שההבדל בפלט של טנסור כזה יהיה גבוה כמו 20-10 = 10.