אחסון במטמון של קומפילציה

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

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

סקירת זרימת עבודה

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

מידע מטמון מסופק והפגיעה במטמון

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

מידע מטמון מסופק ופספוס מטמון

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

מידע מטמון לא מסופק

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

מידע מטמון

מידע הקובץ השמור המסופק למנהל ההתקן מורכב מאסימון ומטפל בקובץ מטמון.

אֲסִימוֹן

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

מטפל בקבצי מטמון (שני סוגים של קבצי מטמון)

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

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

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

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

בִּטָחוֹן

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

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

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

קוד לדוגמה זה מדגים כיצד ליישם את ההיגיון הזה.

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, הנהג אחראי לשחרור חפצי מטמון כאשר הם אינם נחוצים יותר.