בדף הזה מתוארות מבני הנתונים והשיטות שמשמשים לתקשורת יעילה בין מאגרי המידע של המשתנים לבין מנהל ההתקן והמסגרת.
בזמן הידור המודל, המסגרת מספקת ל-driver את הערכים של אופרטורים קבועים. בהתאם לטווח החיים של המשתנה הקבוע, הערכים שלו נמצאים בוקטור HIDL או במאגר זיכרון משותף.
- אם משך החיים הוא
CONSTANT_COPY
, הערכים נמצאים בשדהoperandValues
במבנה המודל. מכיוון שהערכים בוקעים במהלך תקשורת בין תהליכים (IPC), בדרך כלל משתמשים בהם רק כדי לאחסן כמות קטנה של נתונים, כמו אופרטורים סקלריים (לדוגמה, סקלר ההפעלה ב-ADD
) ופרמטרים קטנים של טינסורים (לדוגמה, טינסור הצורה ב-RESHAPE
). - אם משך החיים הוא
CONSTANT_REFERENCE
, הערכים נמצאים בשדהpools
במבנה המודל. רק ה-handles של מאגרי הזיכרון המשותף מוכפלים במהלך IPC, ולא מועתקים הערכים הגולמיים. לכן, יעיל יותר לאחסן כמות גדולה של נתונים (לדוגמה, פרמטרים של משקלים בתהליכי עיבוד נתונים) באמצעות מאגרי זיכרון משותפים מאשר באמצעות וקטורים של HIDL.
בזמן ביצוע המודל, המסגרת מספקת לנהג את מאגרי הנתונים של אופרטורי הקלט והפלט. בניגוד לקבועות בזמן הידור שעשויות להישלח באמצעות וקטור HIDL, נתוני הקלט והפלט של ביצוע תמיד מועברים באמצעות אוסף של מאגרי זיכרון.
סוג הנתונים hidl_memory
ב-HIDL משמש גם בתהליך ה-compilation וגם בתהליך הביצוע כדי לייצג מאגר זיכרון משותף לא ממופה. הנהג צריך למפות את הזיכרון בהתאם כדי שניתן יהיה להשתמש בו על סמך שם סוג הנתונים hidl_memory
.
שמות הזיכרון הנתמכים הם:
ashmem
: זיכרון משותף של Android. מידע נוסף זמין במאמר זיכרון.mmap_fd
: זיכרון משותף שמבוסס על מתאר קובץ דרךmmap
.hardware_buffer_blob
: זיכרון משותף שמבוסס על AHardwareBuffer בפורמטAHARDWARE_BUFFER_FORMAT_BLOB
. זמין מ-Neural Networks (NN) HAL 1.2. מידע נוסף זמין במאמר AHardwareBuffer.hardware_buffer
: זיכרון משותף שמבוסס על AHardwareBuffer כללי שלא משתמש בפורמטAHARDWARE_BUFFER_FORMAT_BLOB
. מאגר החומרה במצב שאינו BLOB נתמך רק בהרצת מודל.הוא זמין מ-NN HAL 1.2. מידע נוסף זמין במאמר AHardwareBuffer.
החל מ-NN HAL 1.3, NNAPI תומך בדומיינים של זיכרון שמספקים ממשקי הקצאה למאגרים בניהול הנהג. אפשר גם להשתמש במאגרים בניהול הנהג ככניסות או כפלט של ביצוע. מידע נוסף זמין במאמר דומיינים של זיכרון.
מנהלי ההתקנים של NNAPI חייבים לתמוך במיפוי של שמות הזיכרון ashmem
ו-mmap_fd
. החל מ-NN HAL 1.3, הנהגים חייבים לתמוך גם במיפוי של hardware_buffer_blob
. התמיכה במצבים hardware_buffer
ודומיינים של זיכרון שאינם BLOB היא אופציונלית.
AHardwareBuffer
AHardwareBuffer הוא סוג של זיכרון משותף שמקיף מאגר של Gralloc. ב-Android 10, ממשק Neural Networks API (NNAPI) תומך בשימוש ב-AHardwareBuffer, שמאפשר לנהג לבצע פעולות בלי להעתיק נתונים, וכך לשפר את הביצועים ואת צריכת האנרגיה של האפליקציות. לדוגמה, סטאק HAL של מצלמה יכול להעביר אובייקטים של AHardwareBuffer ל-NNAPI לעומסי עבודה של למידת מכונה באמצעות אחזורים של AHardwareBuffer שנוצרו על ידי ממשקי ה-API של NDK למצלמה ושל NDK למדיה. מידע נוסף זמין במאמר ANeuralNetworksMemory_createFromAHardwareBuffer
.
אובייקטים מסוג AHardwareBuffer שמשמשים ב-NNAPI מועברים לנהג באמצעות מבנה hidl_memory
בשם hardware_buffer
או hardware_buffer_blob
.
המבנה hidl_memory
hardware_buffer_blob
מייצג רק אובייקטים מסוג AHardwareBuffer בפורמט AHARDWAREBUFFER_FORMAT_BLOB
.
המידע שנדרש למסגרת מקודד בשדה hidl_handle
של המבנה hidl_memory
. השדה hidl_handle
עוטף את השדה native_handle
, שמקודד את כל המטא-נתונים הנדרשים לגבי מאגר AHardwareBuffer או Gralloc.
הנהג צריך לפענח כראוי את השדה hidl_handle
שסופק ולגשת לזיכרון שמתואר על ידי hidl_handle
. כשמתבצעת קריאה ל-method getSupportedOperations_1_2
, getSupportedOperations_1_1
או getSupportedOperations
, הנהג צריך לזהות אם הוא יכול לפענח את hidl_handle
שסופק ולגשת לזיכרון שמתואר על ידי hidl_handle
. הכנת המודל תיכשל אם אין תמיכה בשדה hidl_handle
שמשמש לביטוי קבוע. הביצוע חייב להיכשל אם השדה hidl_handle
שמשמש לפעולה של קלט או פלט של הביצוע לא נתמך. מומלץ שהדרייבר יחזיר את קוד השגיאה GENERAL_FAILURE
אם ההכנה או ההפעלה של המודל נכשלות.
דומיינים של זיכרון
במכשירים עם Android מגרסה 11 ואילך, NNAPI תומך בדומיינים של זיכרון שמספקים ממשקי הקצאה למאגרים בניהול הנהג. כך אפשר להעביר זיכרונות מקומיים של המכשיר בין פעולות, וכך למנוע העתקה וטרנספורמציה מיותרים של נתונים בין פעולות רצופות באותו מנהל. התהליך הזה מוצג באיור 1.
איור 1. מאגר נתונים באמצעות דומיינים של זיכרון
התכונה של תחום הזיכרון מיועדת לטינסורים שרובם פנימיים לנהג ולא צריכים גישה תכופה בצד הלקוח. דוגמאות למטריצות כאלה הן מטריצות המצב במודלים של רצף. בטנסורים שצריך גישה תכופה ל-CPU בצד הלקוח, עדיף להשתמש במאגרי זיכרון משותפים.
כדי לתמוך בתכונה של תחום זיכרון, צריך להטמיע את IDevice::allocate
כדי לאפשר למסגרת לבקש הקצאת מאגר מנוהל על ידי הנהג. במהלך ההקצאה, המסגרת מספקת את המאפיינים ודפוסי השימוש הבאים למאגר:
BufferDesc
מתאר את המאפיינים הנדרשים של המאגר.BufferRole
מתאר את דפוס השימוש הפוטנציאלי של המאגר כקלט או פלט של מודל מוכן. אפשר לציין כמה תפקידים במהלך הקצאת המאגר, וניתן להשתמש במאגר שהוקצה רק בתפקידים שצוינו.
מאגר הנתונים שהוקצה הוא פנימי לנהג. הנהג יכול לבחור כל מיקום של מאגר או פריסה של נתונים. אחרי שהמאגר יוקצה בהצלחה, הלקוח של הנהג יוכל להפנות למאגר או לבצע איתו אינטראקציה באמצעות האסימון המוחזר או האובייקט IBuffer
.
האסימון מ-IDevice::allocate
מסופק כשמתייחסים למאגר כאחד מהאובייקטים של MemoryPool
במבנה Request
של הביצוע. כדי למנוע מתהליך לנסות לגשת למאגר שהוקצה בתהליך אחר, הנהג צריך להחיל אימות מתאים בכל שימוש במאגר. הנהג צריך לאמת שהשימוש במאגר הוא אחד מהתפקידים BufferRole
שסופקו במהלך ההקצאה, ולהפסיק את ההרצה באופן מיידי אם השימוש לא חוקי.
האובייקט IBuffer
משמש להעתקה מפורשת של זיכרון. במצבים מסוימים, הלקוח של הנהג צריך לאתחל את המאגר המנוהל על ידי הנהג ממאגר זיכרון משותף או להעתיק את המאגר למאגר זיכרון משותף. תרחישים לדוגמה:
- אתחול של טינסור המצב
- שמירת תוצאות ביניים במטמון
- ביצוע חלופי במעבד (CPU)
כדי לתמוך בתרחישי השימוש האלה, מנהל ההתקן צריך להטמיע את IBuffer::copyTo
ואת IBuffer::copyFrom
עם ashmem
, mmap_fd
ו-hardware_buffer_blob
, אם הוא תומך בהקצאת דומיינים של זיכרון. אין חובה שהנהג יתמוך במצב שאינו BLOB
hardware_buffer
.
במהלך הקצאת מאגר הנתונים הזמני, אפשר להסיק את המאפיינים של מאגר הנתונים הזמני מהאופרטורים התואמים של המודל של כל התפקידים שצוינו ב-BufferRole
, ומהמאפיינים שצוינו ב-BufferDesc
. כשכל המידע על המאפיינים משולב, יכול להיות שבמאגר הזמני יהיו מאפיינים או דירוג לא ידועים. במקרה כזה, המאגר נמצא במצב גמיש שבו המאפיינים קבועים כשמשתמשים בו כקלט של מודל, ובמצב דינמי כשמשתמשים בו כפלט של מודל. אפשר להשתמש באותו מאגר נתונים זמני עם צורות שונות של פלט בהפעלות שונות, והדרייבר צריך לטפל בגודל המאגר הזמני בצורה נכונה.
תחום הזיכרון הוא תכונה אופציונלית. יכולות להיות כמה סיבות לכך שמנהל התקן לא יכול לתמוך בבקשת הקצאה מסוימת. לדוגמה:
- הגודל של מאגר הנתונים הזמני המבוקש הוא דינמי.
- לנהג יש מגבלות זיכרון שמונעות ממנו לטפל במאגרים גדולים.
כמה שרשורים שונים יכולים לקרוא בו-זמנית מהמאגר המנוהל על ידי הנהג. הגישה למאגר בו-זמנית לכתיבה או לקריאה/כתיבה לא מוגדרת, אבל היא לא יכולה לגרום לקריסה של שירות הנהג או לחסום את מבצע הקריאה ללא הגבלת זמן. הנהג יכול להחזיר שגיאה או להשאיר את תוכן המאגר במצב לא מוגדר.