שמירה במטמון של הידור

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

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

סקירה כללית של תהליך העבודה

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

סופקו פרטי המטמון וההיט של המטמון

  1. האפליקציה מעבירה ספריית שמירה במטמון וסיכום ביקורת (checksum) ייחודיים למודל.
  2. סביבת זמן הריצה של NNAPI מחפשת את קובצי המטמון על סמך סיכום הביקורת, העדפות ביצוע, תוצאת החלוקה למחיצות ומציאת הקבצים.
  3. ה-NNAPI פותח את קובצי המטמון ומעביר את הכינויים לנהג. עם prepareModelFromCache
  4. הנהג מכין את המודל ישירות מקובצי המטמון ומחזיר את המודל את המודל המוכן.

סופקו מידע על המטמון וחסר מידע על המטמון

  1. האפליקציה מעבירה סיכום ביקורת (checksum) ייחודי למודל ושמירה במטמון
  2. סביבת זמן הריצה של NNAPI מחפשת את קובצי השמירה במטמון בהתבסס על סיכום הביקורת, ואת תוצאת החלוקה למחיצות, קבצים במטמון.
  3. NNAPI יוצר קובצי מטמון ריקים בהתבסס על סיכום ביקורת (checksum), ההפעלה החלוקה למחיצות (partitioning), פותחת את קובצי המטמון ומעבירה את ואת המודל לנהג, prepareModel_1_2
  4. מנהל ההתקן אוסף את המודל, כותב מידע ששמור במטמון ומחזירה את המודל המוכן.

לא סופקו פרטים על המטמון

  1. האפליקציה מפעילה אוסף בלי לספק מידע על שמירה במטמון.
  2. האפליקציה לא מעבירה שום דבר שקשור לשמירה במטמון.
  3. זמן הריצה של NNAPI מעביר את המודל לנהג באמצעות prepareModel_1_2
  4. מנהל ההתקן אוסף את המודל ומחזיר את המודל שהוכן.

פרטי המטמון

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

אסימון

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

נקודות אחיזה לקבצים של המטמון (שני סוגים של קובצי מטמון)

שני הסוגים של קובצי מטמון הם מטמון הנתונים ומטמון של המודל.

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

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

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

אבטחה

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

דרך אחת לעשות זאת היא על ידי הנהג לתחזק מפה מהאסימון גיבוב (hash) קריפטוגרפי של המטמון של המודל. הנהג יכול לאחסן את האסימון גיבוב (hash) של המטמון של המודל כששומרים את הידור במטמון. הנהג/ת מבצע/ת בדיקה את הגיבוב החדש של המטמון של המודל עם האסימון המוקלט וצמד הגיבוב, מאחזר את ההידור מהמטמון. המיפוי הזה צריך להיות עקבי בכל להפעיל מחדש את המערכת. הנהג יכול להשתמש Android keystore service, ספריית השירות ב- framework/ml/nn/driver/cache, או כל מנגנון מתאים אחר להטמעת מנהל מיפוי. עם הנהג/ת יש לאתחל מחדש את מנהל המיפוי הזה כדי למנוע הכנת המטמון מגרסה קודמת.

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

הקוד לדוגמה מדגים איך ליישם את הלוגיקה הזו.

bool saveToCache(const sp<V1_2::IPreparedModel> preparedModel,
                 const hidl_vec<hidl_handle>& modelFds, const hidl_vec<hidl_handle>& dataFds,
                 const HidlToken& token) {
    // Serialize the prepared model to internal buffers.
    auto buffers = serialize(preparedModel);

    // This implementation detail is important: the cache hash must be computed from internal
    // buffers instead of cache files to prevent time-of-check to time-of-use (TOCTOU) attacks.
    auto hash = computeHash(buffers);

    // Store the {token, hash} pair to a mapping manager that is persistent across reboots.
    CacheManager::get()->store(token, hash);

    // Write the cache contents from internal buffers to cache files.
    return writeToFds(buffers, modelFds, dataFds);
}

sp<V1_2::IPreparedModel> prepareFromCache(const hidl_vec<hidl_handle>& modelFds,
                                          const hidl_vec<hidl_handle>& dataFds,
                                          const HidlToken& token) {
    // Copy the cache contents from cache files to internal buffers.
    auto buffers = readFromFds(modelFds, dataFds);

    // This implementation detail is important: the cache hash must be computed from internal
    // buffers instead of cache files to prevent time-of-check to time-of-use (TOCTOU) attacks.
    auto hash = computeHash(buffers);

    // Validate the {token, hash} pair by a mapping manager that is persistent across reboots.
    if (CacheManager::get()->validate(token, hash)) {
        // Retrieve the prepared model from internal buffers.
        return deserialize<V1_2::IPreparedModel>(buffers);
    } else {
        return nullptr;
    }
}

תרחישים מתקדמים לדוגמה

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

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

כדי לגשת לתוכן שבמטמון (קריאה או כתיבה) אחרי שיחת ההידור, צריך לוודא שהנהג:

  • כפילות של כינויי הקובץ במהלך הפעלת prepareModel_1_2 או prepareModelFromCache וקורא/ת או מעדכן את המטמון תוכן במועד מאוחר יותר.
  • הטמעת לוגיקה של נעילת קבצים מחוץ לקריאה ההידור הרגילה כדי למנוע כתיבה בו-זמנית עם קריאה או כתיבה אחרת.

הטמעת מנוע שמירה במטמון

בנוסף לממשק השמירה במטמון NN HAL 1.2, אפשר למצוא גם ששומרים במטמון frameworks/ml/nn/driver/cache nnCache ספריית המשנה מכילה קוד אחסון מתמיד שהנהג יכול להטמיע שמירה במטמון של הידור במטמון בלי להשתמש בתכונות השמירה במטמון NNAPI. הטופס הזה של אפשר להטמיע שמירה במטמון של הידור בכל גרסה של תקן NN HAL. אם אפשרות ההטמעה של השמירה במטמון המנותקת מממשק HAL הנהג/ת לשחרור פריטי מידע מהמטמון כשכבר אין בהם צורך.