編譯快取

從 Android 10 開始,Neural Networks API (NNAPI) 提供多種 這會減少編譯用的時間 應用程式啟動時。使用這項快取功能時,驅動程式不會 因此不需管理或清除快取檔案這是選用功能 可以透過 NN HAL 1.2 實作。如要進一步瞭解這個函式 看 ANeuralNetworksCompilation_setCaching

驅動程式也可以獨立於 NNAPI 之外實作編譯快取。這個 無論使用 NNAPI NDK 和 HAL 快取功能,都能實作或 而不是Android 開放原始碼計畫提供低階公用程式庫 (快取引擎)。如要 相關資訊,請參閱「實作快取引擎」。

工作流程總覽

本節說明具有編譯快取功能的一般工作流程

提供的快取資訊和快取命中

  1. 應用程式會傳送快取目錄和模型專屬的總和檢查碼。
  2. NNAPI 執行階段會根據總和檢查碼尋找快取檔案, 執行偏好設定和分區結果,並找到檔案。
  3. NNAPI 會開啟快取檔案,並將控點傳送給驅動程式 同時 prepareModelFromCache
  4. 驅動程式直接從快取檔案準備模型,然後 準備的模型

提供的快取資訊和快取失敗

  1. 應用程式會傳遞模型專屬的總和檢查碼,並傳送快取 目錄。
  2. NNAPI 執行階段會根據總和檢查碼尋找快取檔案, 執行偏好設定,分區結果未找到 快取檔案。
  3. NNAPI 會根據總和檢查碼,建立空白的快取檔案 和分區功能,開啟快取檔案並傳遞 輸出方式和模型傳送給驅動程式 prepareModel_1_2
  4. 驅動程式會編譯模型,並將快取資訊寫入快取 檔案,並傳回準備好的模型

未提供快取資訊

  1. 應用程式會叫用編譯,但不會提供任何快取資訊。
  2. 應用程式不會傳遞任何與快取相關的內容。
  3. NNAPI 執行階段會透過 prepareModel_1_2
  4. 驅動程式會編譯模型,並傳回準備好的模型。

快取資訊

提供給驅動程式的快取資訊包含權杖, 快取檔案控制點。

憑證

符記 為這個 BERT 模型 Constant::BYTE_SIZE_OF_CACHE_TOKEN敬上 用於識別準備模型儲存 快取檔案以及使用 prepareModel_1_2 擷取準備的模型 prepareModelFromCache。驅動程式的用戶端應選擇含有 碰撞率低驅動程式無法偵測符記衝突。碰撞 會導致失敗的執行失敗或成功的執行作業產生 不正確的輸出值

快取檔案控制代碼 (兩種快取檔案)

快取檔案分為兩種類型:「資料快取」和「模型快取」

  • 資料快取:用於快取常數資料,包括預先處理和 經過轉換的張量緩衝區不應修改資料快取 最終效果比在執行時產生錯誤輸出值還要更嚴重 讓應用程式從可以最快做出回應的位置 回應使用者要求
  • 模型快取:用於快取安全機密資料,例如編譯 機器原生二進位格式的可執行機器碼A 罩杯 修改模型快取可能會影響驅動程式的執行作業 讓惡意用戶端利用這項功能執行 授予的權限因此,驅動程式必須檢查模型快取 已損毀。如需更多資訊 請參閱安全性

驅動程式必須決定快取資訊在兩者之間的分配方式 快取檔案類型,並回報每種類型需要多少快取檔案 同時 getNumberOfCacheFilesNeeded

NNAPI 執行階段一律會開啟快取檔案控制代碼,可讀取和寫入 權限。

安全性

在編譯快取中,模型快取可能包含安全性敏感資料,例如 視為已編譯的可執行機器碼,採用裝置的原生二進位格式。如果不是 因此,修改模型快取可能會影響驅動程式 執行行為因為快取內容是儲存在應用程式中 目錄後,用戶端就能修改快取檔案。錯誤用戶端可能會 不小心破壞快取,並且惡意用戶端可以刻意 以便在裝置上執行未經驗證的程式碼。根據用途 裝置特性,那麼這可能是安全性問題。因此, 驅動程式必須能夠偵測 從快取準備模型之前,可能會發生模型快取毀損的情況。

為達成此目的,其中一個方法是讓驅動程式從憑證到 模型快取的加密編譯雜湊值驅動程式可儲存憑證 模型快取的雜湊值。駕駛人檢查 模型快取的新雜湊值,含有記錄的符記和雜湊組合 從快取中擷取編譯資料這個對應關係必須具有 系統就會重新啟動。駕駛人可使用 Android KeyStore 服務是 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;
    }
}

進階用途

在某些進階用途中,驅動程式需要存取快取內容 讀取或寫入。用途範例包括:

  • 及時編譯:編譯會延遲到 首次執行的時間
  • 多階段編譯:一開始會執行快速編譯 稍後會執行選用的最佳化編譯 會視使用頻率而定

如要在編譯呼叫後存取快取內容 (讀取或寫入),請確定 駕駛人:

  • 在叫用 Google AI 時複製檔案控制代碼 prepareModel_1_2prepareModelFromCache,並讀取/更新快取 內容。
  • 在一般編譯呼叫之外實作檔案鎖定邏輯 防止寫入作業與讀取或其他寫入並行。

導入快取引擎

除了 NN HAL 1.2 編譯快取介面之外,您也可以 快取公用程式庫 frameworks/ml/nn/driver/cache敬上 目錄。 nnCache敬上 子目錄包含供驅動程式實作的永久儲存空間程式碼 進行編譯快取,而不使用 NNAPI 快取功能。這種形式 編譯快取功能可以透過任何版本的 NN HAL 執行。如果 驅動程式選擇實作與 HAL 介面中斷連線的快取, 驅動程式是 不再需要快取構件