จาก Android 10, Neural Networks API (NNAPI)
ซึ่งมีฟังก์ชันต่างๆ เพื่อช่วยสนับสนุน
การแคชอาร์ติแฟกต์สำหรับการคอมไพล์ ซึ่งช่วยลดเวลาที่ใช้ในการคอมไพล์
เมื่อแอปเริ่มทำงาน เมื่อใช้ฟังก์ชันการแคชนี้ ไดรเวอร์จะไม่
ต้องจัดการหรือล้างไฟล์ที่แคชไว้ นี่เป็นฟีเจอร์เสริมที่
สามารถใช้ร่วมกับ NN HAL 1.2 ได้ หากต้องการข้อมูลเพิ่มเติมเกี่ยวกับฟังก์ชันนี้
ดู
ANeuralNetworksCompilation_setCaching
ไดรเวอร์ยังใช้การแคชคอมไพล์โดยไม่ขึ้นอยู่กับ NNAPI ได้อีกด้วย ช่วงเวลานี้ สามารถนำไปใช้ได้ ไม่ว่าจะมีการใช้ฟีเจอร์การแคช NNAPI NDK และ HAL หรือ ไม่ได้ AOSP มีไลบรารียูทิลิตีระดับต่ำ (เครื่องมือแคช) สำหรับข้อมูลเพิ่มเติม โปรดดูการใช้เครื่องมือแคช
ภาพรวมเวิร์กโฟลว์
ส่วนนี้จะอธิบายเวิร์กโฟลว์ทั่วไปที่มีฟีเจอร์การแคชการคอมไพล์ ที่มีการนำไปใช้
ข้อมูลแคชที่ระบุและพบแคช
- แอปส่งไดเรกทอรีการแคชและ checksum เฉพาะของโมเดล
- รันไทม์ของ NNAPI จะค้นหาไฟล์แคชตาม checksum ค่ากำหนดการดำเนินการ และผลลัพธ์การแบ่งพาร์ติชัน แล้วค้นหาไฟล์ดังกล่าว
- NNAPI จะเปิดไฟล์แคชและส่งแฮนเดิลไปยังไดรเวอร์
กับ
prepareModelFromCache
- ไดรเวอร์จะเตรียมโมเดลโดยตรงจากไฟล์แคชและส่งคืน โมเดลที่เตรียมไว้
ข้อมูลแคชที่ระบุและแคชหายไป
- แอปส่งการตรวจสอบข้อผิดพลาดเฉพาะของโมเดลและการแคช ไดเรกทอรี
- รันไทม์ NNAPI จะค้นหาไฟล์การแคชตาม checksum ค่ากำหนดการดำเนินการ และผลลัพธ์การแบ่งพาร์ติชัน และไม่พบ ไฟล์แคช
- NNAPI สร้างไฟล์แคชที่ว่างเปล่าตามการตรวจสอบข้อผิดพลาด (Checksum)
และการแบ่งพาร์ติชัน จะเปิดไฟล์แคชและส่ง
แฮนเดิลและโมเดลให้กับคนขับ
prepareModel_1_2
- ไดรเวอร์คอมไพล์โมเดล เขียนข้อมูลการแคชไปยังแคช และแสดงผลโมเดลที่เตรียมไว้
ไม่ได้ระบุข้อมูลแคช
- แอปเรียกใช้การคอมไพล์โดยไม่ให้ข้อมูลการแคชใดๆ
- แอปไม่ได้ให้ข้อมูลใดๆ ที่เกี่ยวข้องกับการแคช
- รันไทม์ NNAPI จะส่งโมเดลไปยังไดรเวอร์ด้วย
prepareModel_1_2
- ไดรเวอร์คอมไพล์โมเดลและส่งโมเดลที่เตรียมไว้คืน
ข้อมูลแคช
ข้อมูลการแคชที่ให้ไว้กับผู้ขับประกอบด้วยโทเค็นและ แฮนเดิลไฟล์แคช
โทเค็น
โทเค็น
เป็นโทเค็นการแคชความยาว
Constant::BYTE_SIZE_OF_CACHE_TOKEN
ที่ระบุโมเดลที่เตรียมไว้ ระบบจะระบุโทเค็นเดียวกันเมื่อบันทึก
แคชไฟล์ด้วย prepareModel_1_2
และดึงข้อมูลโมเดลที่เตรียมไว้ด้วย
prepareModelFromCache
ไคลเอ็นต์ของผู้ขับขี่ควรเลือกโทเค็นที่มี
มีการชนกันต่ำ คนขับไม่พบการชนกันของโทเค็น การชนกัน
ส่งผลให้การดำเนินการล้มเหลว หรือในการดำเนินการที่สำเร็จซึ่ง
ค่าเอาต์พุตไม่ถูกต้อง
แฮนเดิลไฟล์แคช (ไฟล์แคช 2 ประเภท)
ไฟล์แคช 2 ประเภทคือแคชข้อมูลและแคชโมเดล
- แคชข้อมูล: ใช้สำหรับแคชข้อมูลคงที่ รวมถึงข้อมูลที่ประมวลผลล่วงหน้าและ ที่เปลี่ยนรูปแบบบัฟเฟอร์ Tensor การแก้ไขแคชข้อมูลไม่ควร ส่งผลให้เกิดผลลัพธ์แย่กว่าการสร้างค่าเอาต์พุตที่ไม่ถูกต้องขณะดำเนินการ
- แคชโมเดล: ใช้สำหรับแคชข้อมูลที่อ่อนไหวต่อความปลอดภัย เช่น ข้อมูลที่คอมไพล์แล้ว รหัสเครื่องสั่งการในรูปแบบไบนารีของระบบของอุปกรณ์ ต การแก้ไขแคชโมเดลอาจส่งผลต่อการดำเนินการของไดรเวอร์ จนเกินกำหนด แล้วไคลเอ็นต์ที่ประสงค์ร้ายก็อาจใช้สิ่งนี้เพื่อดำเนินการ สิทธิ์ที่ให้ไว้ ดังนั้น ไดรเวอร์ต้องตรวจสอบว่าแคชโมเดล เสียหายก่อนที่จะเตรียมโมเดลจากแคช สำหรับข้อมูลเพิ่มเติม ดูความปลอดภัย
ไดรเวอร์ต้องเลือกวิธีการกระจายข้อมูลแคชระหว่าง
ประเภทไฟล์แคช และรายงานจำนวนไฟล์แคชที่จำเป็นสำหรับแต่ละประเภท
กับ
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;
}
}
Use Case ขั้นสูง
ในกรณีการใช้งานขั้นสูงบางกรณี ไดรเวอร์ต้องใช้สิทธิ์เข้าถึงเนื้อหาแคช (อ่านหรือเขียน) หลังการเรียกการคอมไพล์ ตัวอย่างกรณีการใช้งานมีดังนี้
- การคอมไพล์แบบทันท่วงที: การคอมไพล์จะล่าช้าจนกว่า การดำเนินการครั้งแรก
- การคอมไพล์แบบหลายขั้นตอน: การคอมไพล์แบบรวดเร็วเริ่มต้น และการรวบรวมเนื้อหาที่เพิ่มประสิทธิภาพ (ไม่บังคับ) จะดำเนินการในภายหลัง โดยขึ้นอยู่กับความถี่ในการใช้งาน
หากต้องการเข้าถึงเนื้อหาแคช (อ่านหรือเขียน) หลังการเรียกการคอมไพล์ โปรดตรวจสอบว่า ที่คนขับจะ:
- ทำสำเนาแฮนเดิลไฟล์ระหว่างการเรียกใช้
prepareModel_1_2
หรือprepareModelFromCache
และอ่าน/อัปเดตแคช เนื้อหาในภายหลัง - ใช้ตรรกะการล็อกไฟล์นอกการเรียกใช้การคอมไพล์ปกติ เพื่อป้องกันไม่ให้การเขียนเกิดขึ้นพร้อมกันกับการเขียน (Read) หรือการเขียนอื่นๆ
ติดตั้งเครื่องมือแคช
นอกจากอินเทอร์เฟซการแคชการคอมไพล์ NN HAL 1.2 แล้ว คุณยังสามารถค้นหา
ในไลบรารีของยูทิลิตีแคช
frameworks/ml/nn/driver/cache
ไดเรกทอรี
nnCache
ไดเรกทอรีย่อยมีโค้ดพื้นที่เก็บข้อมูลถาวรสำหรับให้ไดรเวอร์ใช้
การแคชการคอมไพล์โดยไม่ต้องใช้ฟีเจอร์การแคช NNAPI แบบฟอร์มนี้
การแคชคอมไพล์สามารถใช้กับ NN HAL เวอร์ชันใดก็ได้ หาก
ผู้ขับขี่เลือกที่จะใช้การแคช
โดยตัดการเชื่อมต่อจากอินเทอร์เฟซ HAL
คนขับคือ
ซึ่งจะทำหน้าที่ตรึงอาร์ติแฟกต์ที่แคชไว้เมื่อไม่จำเป็นต้องใช้อีกต่อไป