בדף הזה מתוארות מבני הנתונים והשיטות שמשמשים לתקשורת יעילה בין מאגרי המידע של המשתנים לבין מנהל ההתקן והמסגרת.
בזמן הידור המודל, המסגרת מספקת ל-driver את הערכים של אופרטורים קבועים. בהתאם לטווח החיים של המשתנה הקבוע, הערכים שלו נמצאים בוקטור HIDL או במאגר זיכרון משותף.
- אם משך החיים הוא
CONSTANT_COPY
, הערכים נמצאים בשדהoperandValues
במבנה המודל. מכיוון שהערכים בווקטור HIDL מועתקים במהלך תקשורת בין תהליכים (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 שנוצרו על ידי ממשקי ה-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
. כשכל פרטי המאפיינים משולבים, יכול להיות שבמאגר הזמני יהיו מאפיינים או דירוג לא ידועים. במקרה כזה, המאגר נמצא במצב גמיש שבו המאפיינים קבועים כשמשתמשים בו כקלט של מודל, ובמצב דינמי כשמשתמשים בו כפלט של מודל. אפשר להשתמש באותו מאגר נתונים זמני עם צורות שונות של פלט בהפעלות שונות, והדרייבר צריך לטפל בגודל המאגר הזמני בצורה תקינה.
דומיין הזיכרון הוא תכונה אופציונלית. יכולות להיות כמה סיבות לכך שמנהל התקן לא יכול לתמוך בבקשת הקצאה מסוימת. לדוגמה:
- הגודל של מאגר הנתונים הזמני המבוקש הוא דינמי.
- לנהג יש מגבלות זיכרון שמונעות ממנו לטפל במאגרים גדולים.
כמה שרשורים שונים יכולים לקרוא בו-זמנית מהמאגר המנוהל על ידי הנהג. גישה למאגר הנתונים הזמני לצורך כתיבה או קריאה/כתיבה לא מוגדרת, אבל היא לא יכולה לקרוס את שירות הנהג או לחסום את המתקשר ללא הגבלת זמן. הנהג יכול להחזיר שגיאה או להשאיר את תוכן המאגר במצב לא מוגדר.