從 Android 10 開始,Neural Networks API (NNAPI)
提供多種
這會減少編譯用的時間
應用程式啟動時。使用這項快取功能時,驅動程式不會
因此不需管理或清除快取檔案這是選用功能
可以透過 NN HAL 1.2 實作。如要進一步瞭解這個函式
看
ANeuralNetworksCompilation_setCaching
。
驅動程式也可以獨立於 NNAPI 之外實作編譯快取。這個 無論使用 NNAPI NDK 和 HAL 快取功能,都能實作或 而不是Android 開放原始碼計畫提供低階公用程式庫 (快取引擎)。如要 相關資訊,請參閱「實作快取引擎」。
工作流程總覽
本節說明具有編譯快取功能的一般工作流程
提供的快取資訊和快取命中
- 應用程式會傳送快取目錄和模型專屬的總和檢查碼。
- NNAPI 執行階段會根據總和檢查碼尋找快取檔案, 執行偏好設定和分區結果,並找到檔案。
- NNAPI 會開啟快取檔案,並將控點傳送給驅動程式
同時
prepareModelFromCache
。 - 驅動程式直接從快取檔案準備模型,然後 準備的模型
提供的快取資訊和快取失敗
- 應用程式會傳遞模型專屬的總和檢查碼,並傳送快取 目錄。
- NNAPI 執行階段會根據總和檢查碼尋找快取檔案, 執行偏好設定,分區結果未找到 快取檔案。
- NNAPI 會根據總和檢查碼,建立空白的快取檔案
和分區功能,開啟快取檔案並傳遞
輸出方式和模型傳送給驅動程式
prepareModel_1_2
。 - 驅動程式會編譯模型,並將快取資訊寫入快取 檔案,並傳回準備好的模型
未提供快取資訊
- 應用程式會叫用編譯,但不會提供任何快取資訊。
- 應用程式不會傳遞任何與快取相關的內容。
- NNAPI 執行階段會透過
prepareModel_1_2
。 - 驅動程式會編譯模型,並傳回準備好的模型。
快取資訊
提供給驅動程式的快取資訊包含權杖, 快取檔案控制點。
憑證
符記
為這個 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_2
或prepareModelFromCache
,並讀取/更新快取 內容。 - 在一般編譯呼叫之外實作檔案鎖定邏輯 防止寫入作業與讀取或其他寫入並行。
導入快取引擎
除了 NN HAL 1.2 編譯快取介面之外,您也可以
快取公用程式庫
frameworks/ml/nn/driver/cache
敬上
目錄。
nnCache
敬上
子目錄包含供驅動程式實作的永久儲存空間程式碼
進行編譯快取,而不使用 NNAPI 快取功能。這種形式
編譯快取功能可以透過任何版本的 NN HAL 執行。如果
驅動程式選擇實作與 HAL 介面中斷連線的快取,
驅動程式是
不再需要快取構件