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

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

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

HAL של רשתות נוירונים

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

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

זרימה של רשתות נוירונים

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

אתחול

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

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

כדי לקבוע את הערכים שמנהל התקן מחזיר בתגובה ל-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 כולל מידע על ביצועי הנהגים רק עבור נקודה צפה (floating-point) וטנצ'רים כמותיים, ולא כולל סוגי נתונים סקלריים.

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

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

קומפילציה

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

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

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

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

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

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

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

ביצוע

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

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

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

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

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

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

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

אפשר לשלוח כמה בקשות במקביל באותו @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 ראו מסגרת סנכרון.

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

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

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

בקרת זרימה

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

איכות השירות

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

ניקוי

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

שימוש במעבד

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

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

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

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

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

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

  • VLogging: VLOG הוא מאקרו wrapper מסביב ל-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 אם אובייקט ה-NN HAL תקין בהתאם למפרט של גרסת ה-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 מפעיל את הנהגים באופן ישיר (בלי להשתמש ב-framework), ואילו CTS מיישם את הנהגים באופן עקיף דרך המסגרת. הבדיקות האלה בודקות את כל ה-methods של ה-API, ומוודאים שכל הפעולות שנתמכות על ידי מנהלי ההתקנים פועלות כראוי ומספקות תוצאות שעומדות בדרישות הדיוק.

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

  • Floating-point: b(expected - Actual) <= atol + rtol * b(expected); כאשר:

    • ל-fp32, atol = 1e-5f, rtol = 5.0f * 1.1920928955078125e-7
    • ל-fp16, atol = rtol = 5.0f * 0.0009765625f
  • כמותית: כל אחד בנפרד (חוץ מהשנייה 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 Machine Learning Test Suite (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 של רשתות נוירונים

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

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 כולל את כל סוגי הנתונים, כולל סוגי נתונים סקלריים, ומייצג ביצועים לא קשורים באמצעות וקטור במקום שדות עם שם.
  • ה-methods getVersionString ו-getType מאפשרות ל-framework לאחזר את סוג המכשיר (DeviceType) ואת פרטי הגרסה. למידע נוסף, ראו גילוי והקצאה של מכשירים.
  • השיטה executeSynchronously נקראת כברירת מחדל כדי לבצע ביצוע באופן סינכרוני. ה-method execute_1_2 מנחה את ה-framework לבצע הפעלה באופן אסינכרוני. ביצוע
  • הפרמטר MeasureTiming לשיטות executeSynchronously,‏ execute_1_2 והפעלה ברצף מציין אם הנהג מודד את משך ההפעלה. התוצאות מדווחות במבנה Timing. למידע נוסף, ראו תזמון.
  • תמיכה בפעולות שבהן אופרנד אחד או יותר של פלט הוא בעל מאפיין או דירוג לא ידועים. מידע נוסף זמין במאמר צורת הפלט.
  • תמיכה בתוספי ספקים, שהם אוספים של פעולות וסוגי נתונים שהוגדרו על ידי הספק. הנהג מדווח על תוספים נתמכים באמצעות method IDevice::getSupportedExtensions. תוספים של ספקים
  • היכולת של אובייקט זרימה רציפה לשלוט בקבוצה של פעולות זרימה רציפה באמצעות תורים מהירים להעברת הודעות (FMQ) כדי לתקשר בין תהליכי האפליקציה לבין תהליכי הנהג, וכך לצמצם את זמן האחזור. ביצועים רצופי ומהיר של הודעות
  • תמיכה ב-AHardwareBuffer כדי לאפשר למנהל ההתקן לבצע פעולות ללא העתקת נתונים. מידע נוסף זמין במאמר AHardwareBuffer.
  • תמיכה משופרת בשמירת ארטיפקטים של הידור במטמון כדי לקצר את זמן הידור האפליקציה בזמן ההפעלה. למידע נוסף, ראו שמירה במטמון של הידור במטמון.

ב-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
  • תמיכה ב-tensors עם דרגה שונה מ-4 בפעולות softmax ו-normalization
  • תמיכה בקיפולים מורחבים
  • תמיכה בקלט עם קצוב מעורב ב-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/.