מנהלי התקנים של Neural Networks API

בדף הזה מוסבר איך להטמיע מנהל של Neural Networks API‏ (NNAPI). פרטים נוספים זמינים במסמכי העזרה בקובצי ההגדרה של HAL ב-hardware/interfaces/neuralnetworks. הטמעה לדוגמה של מנהל התקן מופיעה בקובץ frameworks/ml/nn/driver/sample.

למידע נוסף על Neural Networks API, ראו Neural Networks API.

Neural Networks HAL

‏HAL של רשתות נוירונליות (NN) מגדיר הפשטה של המכשירים השונים, כמו יחידות עיבוד גרפי (GPU) ומעבדי אותות דיגיטליים (DSP), שנמצאים במוצר (לדוגמה, טלפון או טאבלט). מנהלי ההתקנים של המכשירים האלה חייבים לעמוד בתקן NN HAL. הממשק מוגדר בקובצי ההגדרה של HAL ב-hardware/interfaces/neuralnetworks.

התהליך הכללי של הממשק בין המסגרת לבין הנהג מתואר באיור 1.

תהליך העבודה של רשתות נוירונים

איור 1. תהליך העבודה של רשתות נוירונים

אתחול

במהלך האינטליקציה, המסגרת שולחת לשאילתה לנהג לגבי היכולות שלו באמצעות IDevice::getCapabilities_1_3. המבנה @1.3::Capabilities כולל את כל סוגי הנתונים, ומציג את הביצועים ללא הרפיה באמצעות וקטור.

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

כדי לקבוע את הערכים שהדרייבר מחזיר בתגובה ל-IDevice::getCapabilities_1_3, משתמשים באפליקציית NNAPI למדדי ביצועים כדי למדוד את הביצועים של סוגי הנתונים התואמים. מומלץ להשתמש במודלים MobileNet v1 ו-v2, ‏ asr_float ו-tts_float למדידת הביצועים של ערכים של נקודה צפה באורך 32 ביט, ובמודלים המצטברים של MobileNet v1 ו-v2 למדידת הביצועים של ערכים מצטברים באורך 8 ביט. מידע נוסף זמין במאמר Android Machine Learning Test Suite.

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

כחלק מתהליך האתחול, המסגרת עשויה לשלוח שאילתות לקבלת מידע נוסף באמצעות IDevice::getType,‏ IDevice::getVersionString,‏ IDevice:getSupportedExtensions ו-IDevice::getNumberOfCacheFilesNeeded.

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

קומפילציה

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

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

  • אין תמיכה בסוג הנתונים במנהל.
  • הנהג תומך רק בפעולות עם פרמטרים ספציפיים של קלט. לדוגמה, יכול להיות שמנהל התקן תומך בפעולות 3x3 ו-5x5, אבל לא בפעולות 7x7.
  • לנהג יש מגבלות זיכרון שמונעות ממנו לטפל בגרפים או בקלט גדולים.

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

המסגרת מורה לכל מנהל שנבחר להתכונן להרצה של קבוצת משנה של המודל באמצעות קריאה ל-IDevice::prepareModel_1_3. לאחר מכן, כל מנהל רכיבים יוצר את קבוצת המשנה שלו. לדוגמה, מנהל יכול ליצור קוד או ליצור עותק של המשקלים בסדר מחדש. יכול להיות שיחלוף זמן רב בין הידור המודל לבין ביצוע הבקשות, לכן לא כדאי להקצות משאבים כמו קטעים גדולים של זיכרון המכשיר במהלך הידור.

אם הפעולה מסתיימת בהצלחה, מנהל ההתקן מחזיר אחיזה מסוג @1.3::IPreparedModel. אם מנהל ההתקן מחזיר קוד שגיאה בזמן הכנת קבוצת המשנה שלו מהמודל, המסגרת מפעילה את כל המודל ב-CPU.

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

ביצוע

כשאפליקציה מבקשת מהמסגרת לבצע בקשה, המסגרת קורא כברירת מחדל ל-method‏ HAL‏ IPreparedModel::executeSynchronously_1_3 כדי לבצע ביצוע סינכרוני במודל מוכן. אפשר גם להריץ בקשה באופן אסינכרוני באמצעות השיטה execute_1_3, השיטה executeFenced (ראו ביצוע מוגבל) או באמצעות ביצוע רצף פעולות.

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

כשמשתמשים בשיטה האסינכרונית execute_1_3, השליטה חוזרת לתהליך האפליקציה אחרי שההפעלה מתחילה, והנהג צריך להודיע למסגרת כשההפעלה מסתיימת באמצעות @1.3::IExecutionCallback.

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

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

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

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

אפשר להפעיל כמה בקשות במקביל באותו @1.3::IPreparedModel. הנהג יכול להריץ בקשות במקביל או לבצע את ההרצות בסדר.

המסגרת יכולה לבקש מהנהג לשמור יותר מדגם אחד מוכן. לדוגמה, מכינים את המודל m1, מכינים את m2, מריצים את הבקשה r1 ב-m1, מריצים את r2 ב-m2, מריצים את r3 ב-m1, מריצים את r4 ב-m2, מריצים את m1 (כפי שמתואר בקטע ניקוי) ומריצים את m2.

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

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

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

צורת הפלט

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

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

תזמון

ב-Android 10, אפליקציה יכולה לבקש את זמן הביצוע אם היא ציינה מכשיר יחיד לשימוש בתהליך הידור. מידע נוסף זמין במאמרים MeasureTiming וזיהוי והקצאה של מכשירים. במקרה כזה, נהג NN HAL 1.2 צריך למדוד את משך הביצוע או לדווח על UINT64_MAX (כדי לציין שהמשך לא זמין) בזמן ביצוע הבקשה. מנהל ההתקן צריך לצמצם את הפגיעה בביצועים כתוצאה ממדידת משך הביצוע.

הנהג מדווח על משכי הזמן הבאים במיקרו-שניות במבנה Timing:

  • זמן הביצוע במכשיר: לא כולל את זמן הביצוע בתוכנת ההתקן, שפועלת במעבד המארח.
  • זמן הביצוע ב-driver: כולל זמן הביצוע במכשיר.

משכי הזמן האלה חייבים לכלול את הזמן שבו הביצוע הושעה, למשל כשמשימות אחרות עקפו את הביצוע או כשהמשימות ממתינות למשאב שיהיה זמין.

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

ביצוע מוגבל

ב-Android 11, NNAPI מאפשר להפעלות להמתין לרשימה של מחזיקי sync_fence, ולבחור אם להחזיר אובייקט sync_fence, שיישלח אות כשהפעולה תושלם. כך אפשר לצמצם את התקורה במודלים של רצפים קטנים ובתרחישי שימוש בסטרימינג. בנוסף, ביצוע מגודר מאפשר יכולת פעולה הדדית יעילה יותר עם רכיבים אחרים שיכולים לשלוח אות או להמתין ל-sync_fence. מידע נוסף על sync_fence זמין במאמר מסגרת סנכרון.

בהפעלה מוקפת גדר, המסגרת קוראת ל-method‏ IPreparedModel::executeFenced כדי להפעיל הפעלה אסינכררונית מוקפת גדר במודל מוכן עם וקטור של גדרות סנכרון להמתנה. אם המשימה האסינכרונית מסתיימת לפני שהקריאה חוזרת, אפשר להחזיר למשתנה sync_fence ערך של טיפול (handle) ריק. צריך להחזיר גם אובייקט IFencedExecutionCallback כדי לאפשר למסגרת להריץ שאילתה לגבי סטטוס השגיאה ופרטי משך הזמן.

אחרי השלמת הביצוע, אפשר לשלוח שאילתה דרך IFencedExecutionCallback::getExecutionInfo כדי לקבל את שני ערכי התזמון הבאים, שמשמשים למדידת משך הביצוע.

  • timingLaunched: משך הזמן מהקריאה ל-executeFenced ועד שה-executeFenced מאותת על ה-syncFence המוחזר.
  • timingFenced: משך הזמן מהרגע שבו מתקבל האות מכל מחסומי הסנכרון שההפעלה ממתינה להם, עד שהאות מ-executeFenced מחזיר את הערך syncFence.

בקרת זרימה

במכשירים עם Android מגרסה 11 ואילך, NNAPI כולל שתי פעולות של בקרת תהליך, IF ו-WHILE, שמקבלות מודלים אחרים כארגומנטים ומבצעות אותם באופן מותנה (IF) או חוזר (WHILE). למידע נוסף על הטמעה של הפעולות האלה, ראו בקרת תהליך.

איכות השירות

ב-Android 11, NNAPI כולל שיפורים באיכות השירות (QoS) על ידי מתן אפשרות לאפליקציה לציין את העדיפויות היחסיות של המודלים שלה, את משך הזמן המרבי הצפוי להכנת מודל ואת משך הזמן המרבי הצפוי להשלמת ביצוע. למידע נוסף, ראו איכות שירות.

ניקוי

כשהאפליקציה מסיימת להשתמש במודל מוכן, המסגרת משחררת את ההפניה שלה לאובייקט @1.3::IPreparedModel. כשההפניה לאובייקט IPreparedModel לא קיימת יותר, הוא נהרס באופן אוטומטי בשירות הנהג שיצר אותו. בשלב הזה אפשר למחזר משאבים ספציפיים למודל בהטמעה של ה-destructor בנהג. אם שירות מנהל ההתקן רוצה שהאובייקט IPreparedModel יושמד באופן אוטומטי כשהלקוח לא צריך אותו יותר, הוא לא יכול לשמור הפניות לאובייקט IPreparedModel אחרי שהאובייקט IPreparedeModel הוחזר דרך IPreparedModelCallback::notify_1_3.

שימוש במעבד

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

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

לפעולות שהוצגו ב-Android 10 (רמת API 29) יש רק הטמעה של מעבדי הפניה כדי לוודא שבדיקות CTS ו-VTS תקינות. מומלץ להשתמש בהטמעות האופטימיות שכלולות במסגרות של למידת מכונה לנייד, במקום בהטמעה של NNAPI ל-CPU.

פונקציות שירות

קוד המקור של NNAPI כולל פונקציות שירות ששירותי הנהגים יכולים להשתמש בהן.

הקובץ frameworks/ml/nn/common/include/Utils.h מכיל פונקציות שירות שונות, כמו פונקציות לצורכי רישום ביומן ולצורך המרה בין גרסאות שונות של NN HAL.

  • תיעוד וידאו: VLOG הוא מאקרו של מעטפת סביב LOG של Android, שמתעדה את ההודעה רק אם התג המתאים מוגדר במאפיין debug.nn.vlog. צריך לקרוא לפונקציה initVLogMask() לפני כל קריאה לפונקציה VLOG. אפשר להשתמש במאקרו VLOG_IS_ON כדי לבדוק אם VLOG מופעל כרגע, וכך לדלג על קוד מורכב של רישום ביומן אם הוא לא נדרש. הערך של המאפיין חייב להיות אחד מהערכים הבאים:

    • מחרוזת ריקה, שמציינת שאין לבצע רישום ביומן.
    • האסימון 1 או all, שמציין שצריך לבצע את כל הרישום ביומן.
    • רשימה של תגים, מופרדים באמצעות רווחים, פסיקים או נקודתיים, שמציינת אילו אירועים צריך לתעד ביומן. התגים הם compilation,‏ cpuexe,‏ driver,‏ execution,‏ manager ו-model.
  • compliantWithV1_*: הפונקציה מחזירה את הערך true אם אפשר להמיר אובייקט NN HAL לאותו סוג בגרסה אחרת של HAL בלי לאבד מידע. לדוגמה, קריאה ל-compliantWithV1_0 ב-V1_2::Model מחזירה את הערך false אם המודל כולל סוגי פעולות שהוצגו ב-NN HAL 1.1 או ב-NN HAL 1.2.

  • convertToV1_*: המרת אובייקט NN HAL מגרסה אחת לגרסה אחרת. אם ההמרה גורמת לאובדן מידע (כלומר, אם הגרסה החדשה של הסוג לא יכולה לייצג את הערך באופן מלא), מתועדת אזהרה ביומן.

  • יכולות: אפשר להשתמש בפונקציות nonExtensionOperandPerformance ו-update כדי לעזור ביצירת השדה Capabilities::operandPerformance.

  • שליחת שאילתות לגבי נכסים מסוגים: isExtensionOperandType,‏isExtensionOperationType, ‏nonExtensionSizeOfData,‏nonExtensionOperandSizeOfData, ‏nonExtensionOperandTypeIsScalar,‏tensorHasUnspecifiedDimensions.

הקובץ frameworks/ml/nn/common/include/ValidateHal.h מכיל פונקציות שירות לאימות של אובייקט NN HAL תקין בהתאם למפרט של גרסת ה-HAL שלו.

  • validate*: הפונקציה מחזירה את הערך true אם אובייקט ה-HAL של NN תקין בהתאם למפרט של גרסת ה-HAL שלו. סוגי ה-OEM וסוגים של תוספים לא מאומתים. לדוגמה, הפונקציה validateModel מחזירה את הערך false אם הדגם מכיל פעולה שמפנה למפתח של אופרנד שאינו קיים, או פעולה שאינה נתמכת בגרסה הזו של HAL.

הקובץ frameworks/ml/nn/common/include/Tracing.h מכיל מאקרוסים שמפשטים את הוספת המידע של systracing לקוד של רשתות נוירונליות. לדוגמה, אפשר לעיין בהפעלות המאקרו של NNTRACE_* במנהל ההתקן לדוגמה.

הקובץ frameworks/ml/nn/common/include/GraphDump.h מכיל פונקציית שירות לדמפ של התוכן של Model בצורה גרפית למטרות ניפוי באגים.

  • graphDump: כתיבת ייצוג של המודל בפורמט Graphviz‏ (.dot) בסטרימינג שצוין (אם הוא סופק) או ב-logcat (אם לא סופק סטרימינג).

אימות

כדי לבדוק את ההטמעה של NNAPI, משתמשים בבדיקות VTS ו-CTS שכלולות במסגרת Android. VTS מפעיל את מנהלי ההתקנים ישירות (בלי להשתמש במסגרת), ואילו CTS מפעיל אותם באופן עקיף דרך המסגרת. הבדיקה הזו כוללת בדיקה של כל method ב-API, ולוודא שכל הפעולות הנתמכות על ידי הנהגים פועלות בצורה תקינה ומספקות תוצאות שעומדות בדרישות הדיוק.

הדרישות לדיוק ב-CTS וב-VTS ל-NNAPI הן:

  • נקודת צפה: abs(expected - actual) <= atol + rtol  * abs(expected); כאשר:

    • עבור fp32, ‏ atol = 1e-5f,‏ rtol = 5.0f * 1.1920928955078125e-7
    • עבור fp16,‏ atol = rtol = 5.0f * 0.0009765625f
  • Quantized: שגיאה של יחידה אחת (חוץ מ-mobilenet_quantized, שגיאה של שלוש יחידות)

  • בוליאני: התאמה מדויקת

אחת מהדרכים שבהן CTS בודק את NNAPI היא באמצעות יצירת גרפים פסאודו-אקראיים קבועים, המשמשים לבדיקת תוצאות הביצועים של כל מנהל ולביצוע השוואה ביניהן לבין ההטמעה של NNAPI. עבור מנהלי התקנים עם NN HAL 1.2 ואילך, אם התוצאות לא עומדות בקריטריונים של הדיוק, המערכת של CTS תדווח על שגיאה ותשמיט קובץ מפרט של המודל שנכשל בקטע /data/local/tmp לצורך ניפוי באגים. פרטים נוספים על קריטריונים הדיוק מופיעים במאמרים TestRandomGraph.cpp וTestHarness.h.

בדיקת fuzz

מטרת בדיקת fuzz היא למצוא קריסות, טענות נכוֹנוּת (assertions), הפרות של זיכרון או התנהגות לא מוגדרת באופן כללי בקוד שנבדק, עקב גורמים כמו קלט בלתי צפוי. ב-Android נעשה שימוש בבדיקות מבוססות libFuzzer לבדיקת fuzz של NNAPI. הבדיקות האלה יעילות ב-fuzzing כי הן משתמשות בכיסוי שורות של תרחישי בדיקה קודמים כדי ליצור קלט אקראי חדש. לדוגמה, libFuzzer מעדיף תרחישי בדיקה שפועלים בשורות קוד חדשות. כך ניתן לקצר משמעותית את משך הזמן של הבדיקה עד שמוצאים את הקוד הבעייתי.

כדי לבצע בדיקת fuzz לאימות ההטמעה של מנהל ההתקן, משנים את frameworks/ml/nn/runtime/test/android_fuzzing/DriverFuzzTest.cpp בכלי הבדיקה libneuralnetworks_driver_fuzzer שנמצא ב-AOSP כך שיכלול את קוד מנהל ההתקן. למידע נוסף על בדיקת fuzz של NNAPI, ראו frameworks/ml/nn/runtime/test/android_fuzzing/README.md.

אבטחה

תהליכי האפליקציות מתקשרים ישירות עם תהליך של מנהל התקן, ולכן מנהלי ההתקנים חייבים לאמת את הארגומנטים של הקריאות שהם מקבלים. מערכת VTS מאמתת את התיקוף הזה. קוד האימות מופיע ב-frameworks/ml/nn/common/include/ValidateHal.h.

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

חבילה לבדיקת למידת מכונה ב-Android

ערכת הבדיקות של למידת המכונה ב-Android‏ (MLTS) היא מדד NNAPI שכלול ב-CTS וב-VTS, ומטרתו לאמת את הדיוק של מודלים אמיתיים במכשירי ספקים. בבדיקה נמדדים זמן האחזור והדיוק, והתוצאות של הדרייברים משווים לתוצאות של TF Lite שפועל ב-CPU, עבור אותו מודל ומערך נתונים. כך אפשר להבטיח שהדיוק של מנהל ההתקן לא יהיה גרוע יותר מההטמעה של קובץ העזר של המעבד.

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

מדד הביצועים של NNAPI נמצא בשני פרויקטים ב-AOSP:

מודלים ומערכי נתונים

בבדיקה של NNAPI נעשה שימוש במודלים ובמערכי הנתונים הבאים.

  • MobileNetV1 float ו-u8 quantized בגדלים שונים, שפועלים על קבוצת משנה קטנה (1,500 תמונות) של Open Images Dataset v4.
  • MobileNetV2 float ו-u8 quantized בגדלים שונים, שפועלים על קבוצת משנה קטנה (1,500 תמונות) של Open Images Dataset v4.
  • מודל אקוסטי מבוסס זיכרון לטווח קצר (LSTM) להמרת טקסט לדיבור, שפועל על קבוצת משנה קטנה של קבוצת CMU Arctic.
  • מודל אקוסטי מבוסס-LSTM לזיהוי דיבור אוטומטי, שפועל על קבוצת משנה קטנה של מערך הנתונים LibriSpeech.

מידע נוסף זמין במאמר platform/test/mlts/models.

בדיקת לחץ

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

בכל בדיקות ההתנגשויות מוצגות התכונות הבאות:

  • זיהוי תקיעות: אם לקוח NNAPI נתקע במהלך בדיקה, הבדיקה נכשלת עם הסיבה לכישלון HANG וחבילה הבדיקות עוברת לבדיקה הבאה.
  • זיהוי קריסה של לקוח NNAPI: הבדיקות עוברות קריסות של לקוחות והן נכשלות עם הסיבה לכישלון CRASH.
  • זיהוי קריסה של מנהל התקן: הבדיקות יכולות לזהות קריסה של מנהל התקן שגורמת לכשל בקריאה ל-NNAPI. חשוב לזכור שיכולות להיות קריסות בתהליכי הנהג שלא גורמות לכשל ב-NNAPI ולא גורמות לכישלון הבדיקה. כדי לכסות כשל מסוג זה, מומלץ להריץ את הפקודה tail ביומן המערכת כדי למצוא שגיאות או קריסות שקשורות לדרייבר.
  • טירגוט לכל המאיצים הזמינים: הבדיקה מתבצעת לכל מנהלי ההתקנים הזמינים.

לכל בדיקות התאונות יש ארבע תוצאות אפשריות:

  • SUCCESS: ההפעלה הושלמה ללא שגיאה.
  • FAILURE: ההפעלה נכשלה. בדרך כלל נגרמת בגלל כשל בבדיקת מודל, שמציין שמנהל ההתקן לא הצליח לקמפל או להריץ את המודל.
  • HANG: תהליך הבדיקה הפסיק להגיב.
  • CRASH: תהליך הבדיקה קרס.

מידע נוסף על בדיקות עומס ורשימה מלאה של בדיקות קריסה זמינים במאמר platform/test/mlts/benchmark/README.txt.

שימוש ב-MLTS

כדי להשתמש ב-MLTs:

  1. מחברים מכשיר יעד לתחנת העבודה ומוודאים שאפשר לגשת אליו דרך adb. אם יש יותר ממכשיר אחד שמחובר, מייצאים את משתנה הסביבה ANDROID_SERIAL של מכשיר היעד.
  2. cd לספריית המקור ברמה העליונה של Android.

    source build/envsetup.sh
    lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available.
    ./test/mlts/benchmark/build_and_run_benchmark.sh
    

    בסיום הרצה של מדד ביצועים, התוצאות מוצגות כדף HTML ומועברות אל xdg-open.

מידע נוסף זמין במאמר platform/test/mlts/benchmark/README.txt.

גרסאות HAL של Neural Networks

בקטע הזה מתוארים השינויים בגרסאות HAL של Android ושל Neural Networks.

Android 11

ב-Android 11 מוצגת NN HAL 1.3, שכוללת את השינויים הבולטים הבאים.

  • תמיכה בקידוד 8 ביט חתום ב-NNAPI. הוספת סוג המשתנה TENSOR_QUANT8_ASYMM_SIGNED. מנהלי התקנים עם NN HAL 1.3 שתומכים בפעולות עם קצוב ללא סימן חייבים לתמוך גם בוריאנטים החתומים של הפעולות האלה. כשמריצים גרסאות חתומות ולא חתומות של רוב הפעולות המקווננות, הנהגים חייבים לספק את אותן תוצאות עד להיסט של 128. יש חמישה יוצאים מן הכלל לדרישה הזו: CAST,‏ HASHTABLE_LOOKUP,‏ LSH_PROJECTION,‏ PAD_V2 וגם QUANTIZED_16BIT_LSTM. הפעולה QUANTIZED_16BIT_LSTM לא תומכת באופרטורים עם סימן, ואילו ארבע הפעולות האחרות תומכות בקידוד מדויק עם סימן, אבל לא מחייבות שהתוצאות יהיו זהות.
  • תמיכה בהפעלות מוקפות שבהן המסגרת קוראת לשיטה IPreparedModel::executeFenced כדי להפעיל הפעלה אסינכרונית מוקפת במודל מוכן עם וקטור של מחסומי סנכרון להמתנה. מידע נוסף זמין במאמר ביצוע מוגבל.
  • תמיכה בזרימת בקרה. הוספת הפעולות IF ו-WHILE, שמקבלות מודלים אחרים כארגומנטים ומבצעות אותם באופן מותנה (IF) או שוב ושוב (WHILE). מידע נוסף זמין במאמר זרימת בקרה.
  • שיפור באיכות השירות (QoS), כי האפליקציות יכולות לציין את העדיפויות היחסיות של המודלים שלהן, את משך הזמן המקסימלי הצפוי להכנת מודל ואת משך הזמן המקסימלי הצפוי להשלמת ביצוע. מידע נוסף זמין במאמר איכות שירות.
  • תמיכה בדומיינים של זיכרון שמספקים ממשקי הקצאה למאגרים בניהול הנהג. כך אפשר להעביר זיכרונות מקומיים של המכשיר בין פעולות, וכך למנוע העתקה וטרנספורמציה מיותרים של נתונים בין פעולות רצופות באותו מנהל. מידע נוסף זמין במאמר דומיינים של זיכרון.

Android 10

ב-Android 10 מוצגת NN HAL 1.2, שכוללת את השינויים הבולטים הבאים.

  • המבנה Capabilities כולל את כל סוגי הנתונים, כולל סוגי נתונים סקלריים, ומייצג ביצועים ללא הרפיה באמצעות וקטור במקום שדות עם שמות.
  • השיטות getVersionString ו-getType מאפשרות למסגרת לאחזר את סוג המכשיר (DeviceType) ואת פרטי הגרסה. גילוי והקצאה של מכשירים
  • השיטה executeSynchronously נקראת כברירת מחדל כדי לבצע ביצוע באופן סינכרוני. השיטה execute_1_2 מורה למסגרת לבצע את ההפעלה באופן אסינכרוני. ביצוע
  • הפרמטר MeasureTiming לשיטות executeSynchronously,‏ execute_1_2 והפעלה רציפה מציין אם הנהג מודד את משך ההפעלה. התוצאות מדווחות במבנה Timing. מידע נוסף זמין בקטע תזמון.
  • תמיכה בהרצות שבהן למשתני הפלט יש מימד או דירוג לא ידועים. מידע נוסף זמין במאמר צורת הפלט.
  • תמיכה בתוספים של ספקים, שהם אוספים של פעולות וסוגי נתונים שהוגדרו על ידי הספק. הנהג מדווח על התוספים הנתמכים באמצעות השיטה IDevice::getSupportedExtensions. תוספים של ספקים
  • היכולת של אובייקט זרימה רציפה לשלוט בקבוצה של פעולות זרימה רציפה באמצעות תורים מהירים להעברת הודעות (FMQ) כדי לתקשר בין תהליכי האפליקציה לבין תהליכי הנהג, וכך לצמצם את זמן האחזור. ביצועים רצופי והודעות מהירות
  • תמיכה ב-AHardwareBuffer כדי לאפשר למנהל ההתקן לבצע פעולות ללא העתקת נתונים. מידע נוסף זמין במאמר AHardwareBuffer.
  • תמיכה משופרת בשמירת ארטיפקטים של הידור במטמון כדי לקצר את זמן הידור האפליקציה בזמן ההפעלה. אחסון ב-cache של הידור

ב-Android 10 נוספו סוגי אופרטורים ופעולות הבאות.

  • סוגי אופרטורים

    • ANEURALNETWORKS_BOOL
    • ANEURALNETWORKS_FLOAT16
    • ANEURALNETWORKS_TENSOR_BOOL8
    • ANEURALNETWORKS_TENSOR_FLOAT16
    • ANEURALNETWORKS_TENSOR_QUANT16_ASYMM
    • ANEURALNETWORKS_TENSOR_QUANT16_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM
    • ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
  • פעולות

    • ANEURALNETWORKS_ABS
    • ANEURALNETWORKS_ARGMAX
    • ANEURALNETWORKS_ARGMIN
    • ANEURALNETWORKS_AXIS_ALIGNED_BBOX_TRANSFORM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_BIDIRECTIONAL_SEQUENCE_RNN
    • ANEURALNETWORKS_BOX_WITH_NMS_LIMIT
    • ANEURALNETWORKS_CAST
    • ANEURALNETWORKS_CHANNEL_SHUFFLE
    • ANEURALNETWORKS_DETECTION_POSTPROCESSING
    • ANEURALNETWORKS_EQUAL
    • ANEURALNETWORKS_EXP
    • ANEURALNETWORKS_EXPAND_DIMS
    • ANEURALNETWORKS_GATHER
    • ANEURALNETWORKS_GENERATE_PROPOSALS
    • ANEURALNETWORKS_GREATER
    • ANEURALNETWORKS_GREATER_EQUAL
    • ANEURALNETWORKS_GROUPED_CONV_2D
    • ANEURALNETWORKS_HEATMAP_MAX_KEYPOINT
    • ANEURALNETWORKS_INSTANCE_NORMALIZATION
    • ANEURALNETWORKS_LESS
    • ANEURALNETWORKS_LESS_EQUAL
    • ANEURALNETWORKS_LOG
    • ANEURALNETWORKS_LOGICAL_AND
    • ANEURALNETWORKS_LOGICAL_NOT
    • ANEURALNETWORKS_LOGICAL_OR
    • ANEURALNETWORKS_LOG_SOFTMAX
    • ANEURALNETWORKS_MAXIMUM
    • ANEURALNETWORKS_MINIMUM
    • ANEURALNETWORKS_NEG
    • ANEURALNETWORKS_NOT_EQUAL
    • ANEURALNETWORKS_PAD_V2
    • ANEURALNETWORKS_POW
    • ANEURALNETWORKS_PRELU
    • ANEURALNETWORKS_QUANTIZE
    • ANEURALNETWORKS_QUANTIZED_16BIT_LSTM
    • ANEURALNETWORKS_RANDOM_MULTINOMIAL
    • ANEURALNETWORKS_REDUCE_ALL
    • ANEURALNETWORKS_REDUCE_ANY
    • ANEURALNETWORKS_REDUCE_MAX
    • ANEURALNETWORKS_REDUCE_MIN
    • ANEURALNETWORKS_REDUCE_PROD
    • ANEURALNETWORKS_REDUCE_SUM
    • ANEURALNETWORKS_RESIZE_NEAREST_NEIGHBOR
    • ANEURALNETWORKS_ROI_ALIGN
    • ANEURALNETWORKS_ROI_POOLING
    • ANEURALNETWORKS_RSQRT
    • ANEURALNETWORKS_SELECT
    • ANEURALNETWORKS_SIN
    • ANEURALNETWORKS_SLICE
    • ANEURALNETWORKS_SPLIT
    • ANEURALNETWORKS_SQRT
    • ANEURALNETWORKS_TILE
    • ANEURALNETWORKS_TOPK_V2
    • ANEURALNETWORKS_TRANSPOSE_CONV_2D
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_LSTM
    • ANEURALNETWORKS_UNIDIRECTIONAL_SEQUENCE_RNN

ב-Android 10 יש עדכונים לרבות מהפעולות הקיימות. העדכונים קשורים בעיקר לנושאים הבאים:

  • תמיכה בפריסה של זיכרון NCHW
  • תמיכה בטנסורים עם דרגה שונה מ-4 בפעולות softmax ו-normalization
  • תמיכה במודלים של עיבוד נתונים (convolution) מורחבים
  • תמיכה בקלט עם קצירה משולבת ב-ANEURALNETWORKS_CONCATENATION

ברשימה הבאה מפורטות הפעולות ששונו ב-Android 10. פרטים מלאים על השינויים מופיעים בקטע OperationCode במסמכי העזרה של NNAPI.

  • ANEURALNETWORKS_ADD
  • ANEURALNETWORKS_AVERAGE_POOL_2D
  • ANEURALNETWORKS_BATCH_TO_SPACE_ND
  • ANEURALNETWORKS_CONCATENATION
  • ANEURALNETWORKS_CONV_2D
  • ANEURALNETWORKS_DEPTHWISE_CONV_2D
  • ANEURALNETWORKS_DEPTH_TO_SPACE
  • ANEURALNETWORKS_DEQUANTIZE
  • ANEURALNETWORKS_DIV
  • ANEURALNETWORKS_FLOOR
  • ANEURALNETWORKS_FULLY_CONNECTED
  • ANEURALNETWORKS_L2_NORMALIZATION
  • ANEURALNETWORKS_L2_POOL_2D
  • ANEURALNETWORKS_LOCAL_RESPONSE_NORMALIZATION
  • ANEURALNETWORKS_LOGISTIC
  • ANEURALNETWORKS_LSH_PROJECTION
  • ANEURALNETWORKS_LSTM
  • ANEURALNETWORKS_MAX_POOL_2D
  • ANEURALNETWORKS_MEAN
  • ANEURALNETWORKS_MUL
  • ANEURALNETWORKS_PAD
  • ANEURALNETWORKS_RELU
  • ANEURALNETWORKS_RELU1
  • ANEURALNETWORKS_RELU6
  • ANEURALNETWORKS_RESHAPE
  • ANEURALNETWORKS_RESIZE_BILINEAR
  • ANEURALNETWORKS_RNN
  • ANEURALNETWORKS_ROI_ALIGN
  • ANEURALNETWORKS_SOFTMAX
  • ANEURALNETWORKS_SPACE_TO_BATCH_ND
  • ANEURALNETWORKS_SPACE_TO_DEPTH
  • ANEURALNETWORKS_SQUEEZE
  • ANEURALNETWORKS_STRIDED_SLICE
  • ANEURALNETWORKS_SUB
  • ANEURALNETWORKS_SVDF
  • ANEURALNETWORKS_TANH
  • ANEURALNETWORKS_TRANSPOSE

Android 9

NN HAL 1.1 נוסף ל-Android 9 וכולל את השינויים הבולטים הבאים.

  • IDevice::prepareModel_1_1 כולל פרמטר ExecutionPreference. הנהג יכול להשתמש בנתונים האלה כדי לשנות את ההכנה, מתוך ידיעה שהאפליקציה מעדיפה לחסוך בסוללה או שתפעיל את המודל בקריאות מהירות רצופות.
  • נוספו תשע פעולות חדשות: BATCH_TO_SPACE_ND, DIV, MEAN, PAD, SPACE_TO_BATCH_ND, SQUEEZE, STRIDED_SLICE, SUB, TRANSPOSE.
  • כדי לציין שאפליקציה יכולה להריץ חישובים של 32 ביט של float באמצעות טווח או דיוק של 16 ביט של float, מגדירים את Model.relaxComputationFloat32toFloat16 כ-true. למבנה Capabilities יש את השדה הנוסף relaxedFloat32toFloat16Performance כדי שהנהג יוכל לדווח על הביצועים המנוהלים שלו למסגרת.

Android 8.1

הגרסה הראשונית של Neural Networks HAL (1.0) שוחררה ב-Android 8.1. למידע נוסף, ראו /neuralnetworks/1.0/.