ذخیره کردن ترجمه در حافظه نهان

از Android 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 فایل‌های حافظه نهان خالی را براساس جمع‌آزما، اولویت اجرا، و پارتیشن‌بندی ایجاد می‌کند، فایل‌های حافظه نهان را باز می‌کند، و دستگیره‌ها و مدل را با prepareModel_1_2 به درایور ارسال می‌کند.
  4. گرداننده مدل را گردآوری می‌کند، اطلاعات ذخیره‌سازی نهان را در فایل‌های نهان‌سازی می‌نویسد، و مدل آماده‌شده را برمی‌گرداند.

اطلاعات حافظه نهان ارائه نشده است

  1. برنامه بدون ارائه اطلاعات ذخیره کردن در حافظه نهان، فراخوانی ترجمه می‌کند.
  2. برنامه هیچ چیزی را که به ذخیره موقت مربوط باشد منتقل نمی‌کند.
  3. زمان اجرای NNAPI مدل را با prepareModel_1_2 به درایور منتقل می‌کند.
  4. گرداننده مدل را گردآوری می‌کند و مدل آماده‌شده را برمی‌گرداند.

اطلاعات حافظه نهان

اطلاعات ذخیره‌سازی موقت که به درایور ارائه می‌شود شامل یک کد و دسته‌های فایل حافظه پنهان است.

کد

توکن یک توکن ذخیره‌سازی موقت با طول Constant::BYTE_SIZE_OF_CACHE_TOKEN است که مدل آماده‌شده را شناسایی می‌کند. هنگام ذخیره کردن فایل‌های حافظه نهان با prepareModel_1_2 و بازیابی مدل آماده‌شده با prepareModelFromCache، همان کد ارائه می‌شود. کاربر راننده باید نشانه‌ای با نرخ تصادم پایین انتخاب کند. راننده نمی‌تواند تصادم نشان را تشخیص دهد. تصادم منجر به اجرای ناموفق یا اجرای موفقی می‌شود که مقادیر برونداد نادرست تولید می‌کند.

دسته‌های فایل حافظه نهان (دو نوع فایل حافظه نهان)

دو نوع فایل حافظه نهان وجود دارد: حافظه نهان داده و حافظه نهان مدل.

  • حافظه نهان داده: برای ذخیره کردن داده‌های ثابت در حافظه نهان، ازجمله میان‌گیرهای تانسور پیش‌پردازش‌شده و تبدیل‌شده، استفاده می‌شود. اصلاح حافظه نهان داده نباید منجر به تأثیری بدتر از تولید مقادیر خروجی بد در زمان اجرا شود.
  • حافظه نهان مدل: برای ذخیره کردن داده‌های حساس به امنیت در حافظه نهان، مثل کد ماشینی اجرایی کامپایل‌شده در قالب دودویی بومی دستگاه، استفاده می‌شود. تغییر در حافظه نهان مدل ممکن است بر رفتار اجرای درایور تأثیر بگذارد و یک کارخواه مخرب می‌تواند از این موضوع برای اجرا فراتر از اجازه اعطاشده استفاده کند. بنابراین، درایور باید قبل‌از آماده‌سازی مدل از حافظه نهان، بررسی کند که آیا حافظه نهان مدل خراب است یا نه. برای اطلاعات بیشتر، به امنیت مراجعه کنید.

راه‌انداز باید تصمیم بگیرد که اطلاعات حافظه نهان چگونه بین دو نوع فایل حافظه نهان توزیع شود و گزارش دهد که برای هر نوع به چند فایل حافظه نهان نیاز دارد. getNumberOfCacheFilesNeeded.

زمان اجرای NNAPI همیشه دسته‌های فایل حافظه نهان را با اجازه خواندن و نوشتن باز می‌کند.

امنیت

در حافظه نهان گردآوری، حافظه نهان مدل ممکن است حاوی داده‌های حساس به امنیت باشد، مثل کد ماشین اجرایی گردآوری‌شده در قالب باینری بومی دستگاه. اگر به‌درستی محافظت نشود، تغییر در حافظه نهان مدل ممکن است بر رفتار اجرایی راه‌انداز تأثیر بگذارد. ازآنجایی‌که محتویات حافظه نهان در دایرکتوری برنامه ذخیره می‌شود، فایل‌های حافظه نهان توسط مشتری قابل‌اصلاح هستند. کاربر معیوب ممکن است به‌طور تصادفی حافظه نهان را خراب کند، و کاربر مخرب می‌تواند به‌طور عمدی از این برای اجرای کد تأییدنشده در دستگاه استفاده کند. بسته به ویژگی‌های دستگاه، این ممکن است مشکل امنیتی باشد. بنابراین، راه‌انداز باید بتواند خرابی احتمالی حافظه نهان مدل را قبل‌از آماده‌سازی مدل از حافظه نهان تشخیص دهد.

یکی از راه‌های انجام این کار این است که درایور نقشه‌ای از کد به درهم‌سازی رمزنگاری‌شده حافظه نهان مدل نگهداری کند. وقتی در حافظه نهان ذخیره می‌کنید، درایور می‌تواند نشان و درهم‌سازی حافظه نهان مدلش را ذخیره کند. هنگام بازیابی کامپایل از حافظه نهان، درایور درهم‌سازی جدید حافظه نهان مدل را با جفت درهم‌سازی و داده‌واحد ثبت‌شده بررسی می‌کند. این نگاشت باید در بازراه‌اندازی‌های سیستم ماندگار باشد. راننده می‌تواند از خدمات انبار کلید Android، کتابخانه کاربری در 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 پیاده‌سازی کند، درایور مسئول آزاد کردن مصنوعات ذخیره‌شده در حافظه نهان است، زمانی که دیگر به آن‌ها نیازی نباشد.