API โครงข่ายระบบประสาทเทียมของ Android (NNAPI) คือ Android C API ที่ออกแบบมาเพื่อการเรียกใช้ การดำเนินงานด้านการคำนวณอย่างหนักสำหรับแมชชีนเลิร์นนิงในอุปกรณ์ Android NNAPI ได้รับการออกแบบมาเพื่อมอบฟังก์ชันชั้นฐานสำหรับระดับที่สูงกว่า เฟรมเวิร์กแมชชีนเลิร์นนิง เช่น TensorFlow Lite และ Caffe2 ที่สร้างและฝึกโครงข่ายประสาท API พร้อมใช้งาน ในอุปกรณ์ Android ทั้งหมดที่ใช้ Android 8.1 (API ระดับ 27) ขึ้นไป
NNAPI รองรับการแทรกกรอบโดยการใช้ข้อมูลจากอุปกรณ์ Android กับอุปกรณ์ โมเดลที่นักพัฒนาซอฟต์แวร์กำหนดและได้รับการฝึกแล้ว ตัวอย่างของการกำหนดกรอบ ได้แก่ การแยกประเภท การคาดการณ์พฤติกรรมของผู้ใช้ และเลือกคำตอบที่เหมาะสมให้กับ คำค้นหา
การละเมิดในอุปกรณ์มีประโยชน์หลายประการดังนี้
- เวลาในการตอบสนอง: คุณไม่จำเป็นต้องส่งคำขอผ่านการเชื่อมต่อเครือข่าย และ รอการตอบกลับ ตัวอย่างเช่น สิ่งนี้อาจมีความสำคัญสำหรับแอปพลิเคชันวิดีโอ ซึ่งประมวลผลเฟรมต่อเนื่อง ที่มาจากกล้อง
- ความพร้อมใช้งาน: แอปพลิเคชันจะทำงานแม้อยู่นอกการครอบคลุมเครือข่าย
- ความเร็ว: ฮาร์ดแวร์ใหม่ที่ใช้สำหรับการประมวลผลโครงข่ายระบบประสาทเทียมโดยเฉพาะ ให้การคำนวณที่รวดเร็วกว่า CPU สำหรับการใช้งานทั่วไปเพียงอย่างเดียว
- ความเป็นส่วนตัว: จะไม่มีการส่งข้อมูลออกจากอุปกรณ์ Android
- ต้นทุน: ไม่ต้องมีเซิร์ฟเวอร์ฟาร์มเมื่อคำนวณทั้งหมด อุปกรณ์ Android
แต่ก็มีข้อดีและข้อเสียต่างๆ ที่นักพัฒนาแอปควรคำนึงถึงดังนี้
- การใช้งานระบบ: การประเมินโครงข่ายประสาทเกี่ยวข้องกับ ซึ่งอาจเพิ่มการใช้พลังงานแบตเตอรี่ คุณควรพิจารณา การตรวจสอบประสิทธิภาพแบตเตอรี่ถ้าสิ่งนี้เป็นข้อกังวลสำหรับแอปของคุณ โดยเฉพาะอย่างยิ่ง สำหรับการคำนวณเป็นเวลานาน
- ขนาดแอปพลิเคชัน: ให้ความสำคัญกับขนาดของโมเดล โมเดลอาจ ใช้พื้นที่ว่างหลายเมกะไบต์ การรวมโมเดลขนาดใหญ่ไว้ใน APK จะส่งผลกระทบต่อผู้ใช้อย่างไม่เหมาะสม คุณอาจต้องลองดาวน์โหลด หลังการติดตั้งแอป การใช้โมเดลที่เล็กลง หรือการเรียกใช้ การคำนวณในระบบคลาวด์ NNAPI ไม่มีฟังก์ชันสำหรับการเรียกใช้ โมเดลต่างๆ ในระบบคลาวด์
โปรดดู ตัวอย่าง API โครงข่ายระบบประสาทเทียมของ Android เพื่อดูตัวอย่างวิธีใช้ NNAPI
ทำความเข้าใจรันไทม์ของ Neural Networks API
NNAPI มีชื่อโดยไลบรารีแมชชีนเลิร์นนิง เฟรมเวิร์ก และเครื่องมือ ที่ช่วยให้นักพัฒนาแอปฝึกโมเดลนอกอุปกรณ์และทำให้ใช้งานได้ใน Android อุปกรณ์ โดยทั่วไปแอปจะไม่ใช้ NNAPI โดยตรง แต่จะใช้ ใช้เฟรมเวิร์กแมชชีนเลิร์นนิง ในระดับสูงกว่า เฟรมเวิร์กเหล่านี้สามารถใช้ NNAPI สำหรับดำเนินการอนุมานการเร่งฮาร์ดแวร์ในอุปกรณ์ที่รองรับ
อิงตามข้อกำหนดของแอปและความสามารถของฮาร์ดแวร์ใน Android รันไทม์เครือข่ายระบบประสาทเทียมของ Android สามารถกระจาย ภาระงานการคำนวณของตัวประมวลผลในอุปกรณ์ที่พร้อมใช้งาน รวมถึงหน่วยประมวลผลเฉพาะ ฮาร์ดแวร์เครือข่ายระบบประสาท หน่วยประมวลผลกราฟิก (GPU) และสัญญาณดิจิทัล โปรเซสเซอร์ (DSP)
รันไทม์ของ NNAPI สำหรับอุปกรณ์ Android ที่ไม่มีไดรเวอร์ของผู้ให้บริการเฉพาะ ดำเนินการตามคำขอบน CPU
รูปที่ 1 แสดงสถาปัตยกรรมระบบระดับสูงสำหรับ NNAPI
![](https://developer.android.google.cn/static/ndk/images/nnapi/nnapi_architecture.png?authuser=0000&hl=th)
โมเดลการเขียนโปรแกรม API เครือข่ายระบบประสาท
หากต้องการคำนวณโดยใช้ NNAPI ก่อนอื่นคุณต้องสร้างคำสั่ง กราฟที่กำหนดการคำนวณที่จะดำเนินการ กราฟการคำนวณนี้ เมื่อ กับข้อมูลที่คุณป้อน (เช่น น้ำหนักและความลำเอียงที่ส่งต่อมาจาก เฟรมเวิร์กแมชชีนเลิร์นนิง) เป็นต้นแบบสำหรับการประเมินรันไทม์ของ NNAPI
NNAPI ใช้นามธรรมหลักๆ 4 แบบดังนี้
- โมเดล: กราฟการคำนวณของการดำเนินการทางคณิตศาสตร์และค่าคงที่
คุณค่าที่ได้เรียนรู้ผ่านกระบวนการฝึกอบรม การดำเนินการเหล่านี้เจาะจงสำหรับ
โครงข่ายระบบประสาทเทียม ซึ่งประกอบด้วย 2 มิติ (2 มิติ)
Convolution
โลจิสติกส์
(sigmoid)
การเปิดใช้งาน
เส้นตรง
(ReLU) และอื่นๆ การสร้างโมเดลเป็นการดำเนินการแบบซิงโครนัส
เมื่อสร้างเรียบร้อยแล้ว ก็สามารถนำกลับมาใช้ซ้ำในชุดข้อความและการรวบรวมได้
ใน NNAPI โมเดลจะแสดงเป็น
ANeuralNetworksModel
อินสแตนซ์ - การคอมไพล์: แสดงการกำหนดค่าสำหรับการคอมไพล์โมเดล NNAPI ลงใน
ระดับต่ำลงมา การสร้างการคอมไพล์เป็นการดำเนินการแบบซิงโครนัส ครั้งเดียว
สำเร็จ สามารถนำมาใช้ซ้ำในเทรดและการดำเนินการต่างๆ ได้ ใน
NNAPI คอมไพล์แต่ละรายการจะแสดงเป็น
ANeuralNetworksCompilation
อินสแตนซ์ - หน่วยความจำ: หมายถึงหน่วยความจำที่ใช้ร่วมกัน ไฟล์ที่แมปจากหน่วยความจำ และหน่วยความจำที่คล้ายกัน
บัฟเฟอร์ การใช้บัฟเฟอร์หน่วยความจำทำให้รันไทม์ NNAPI โอนข้อมูลไปยังไดรเวอร์ได้
ได้อย่างมีประสิทธิภาพมากขึ้น โดยทั่วไปแล้วแอปจะสร้างบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกัน 1 ส่วนซึ่ง
มี Tensor ทุกรายการที่ต้องใช้ในการกำหนดโมเดล คุณยังใช้หน่วยความจำได้
เพื่อจัดเก็บอินพุตและเอาต์พุตสำหรับอินสแตนซ์การดำเนินการ ใน NNAPI
บัฟเฟอร์หน่วยความจำแต่ละภาพจะแสดงเป็น
ANeuralNetworksMemory
อินสแตนซ์ การดำเนินการ: อินเทอร์เฟซสำหรับการใช้โมเดล NNAPI กับชุดอินพุตและ รวบรวมผลลัพธ์ การดำเนินการอาจทำแบบซิงโครนัสหรืออะซิงโครนัสก็ได้
สำหรับการดำเนินการแบบไม่พร้อมกัน เทรดหลายรายการ จะรอในการดำเนินการเดียวกันได้ เมื่อการดำเนินการนี้เสร็จสมบูรณ์ เทรดทั้งหมดจะ เผยแพร่แล้ว
ใน NNAPI การดำเนินการแต่ละรายการจะแสดงเป็น
ANeuralNetworksExecution
อินสแตนซ์
รูปที่ 2 แสดงขั้นตอนการเขียนโปรแกรมพื้นฐาน
![](https://developer.android.google.cn/static/ndk/images/nnapi/nnapi_flow.png?authuser=0000&hl=th)
เนื้อหาที่เหลือของส่วนนี้จะอธิบายขั้นตอนในการตั้งค่าโมเดล NNAPI ดำเนินการคำนวณ คอมไพล์โมเดล และเรียกใช้โมเดลที่คอมไพล์
ให้สิทธิ์เข้าถึงข้อมูลการฝึก
ระบบอาจเก็บข้อมูลน้ำหนักและน้ำหนักที่ฝึกแล้วไว้ในไฟล์ หากต้องการจัดเตรียม
รันไทม์ NNAPI ที่มีการเข้าถึงข้อมูลนี้อย่างมีประสิทธิภาพ
ANeuralNetworksMemory
โดยการเรียกฟังก์ชัน
ANeuralNetworksMemory_createFromFd()
และส่งไปในข้อบ่งชี้ไฟล์ของไฟล์ข้อมูลที่เปิดอยู่ และคุณยัง
ระบุแฟล็กการป้องกันหน่วยความจำและออฟเซ็ตที่มีพื้นที่หน่วยความจำที่แชร์
เริ่มต้นในไฟล์
// Create a memory buffer from the file that contains the trained data
ANeuralNetworksMemory* mem1 = NULL;
int fd = open("training_data", O_RDONLY);
ANeuralNetworksMemory_createFromFd(file_size, PROT_READ, fd, 0, &mem1);
แม้ว่าในตัวอย่างนี้ เราจะใช้
ANeuralNetworksMemory
สำหรับน้ำหนักทั้งหมดของเรา ก็อาจจะใช้
ANeuralNetworksMemory
อินสแตนซ์สำหรับหลายไฟล์
ใช้บัฟเฟอร์ของฮาร์ดแวร์เนทีฟ
คุณใช้บัฟเฟอร์ฮาร์ดแวร์เนทีฟได้
สำหรับอินพุตโมเดล เอาต์พุต และค่าตัวถูกดำเนินการคงที่ ในบางกรณี
NNAPI Accelerator สามารถเข้าถึง
AHardwareBuffer
อ็อบเจ็กต์โดยที่ไดรเวอร์ไม่จำเป็นต้องคัดลอกข้อมูล AHardwareBuffer
มีหลายรายการ
การกำหนดค่าต่างกัน และ NNAPI Accelerator บางรายการอาจสนับสนุน
การกำหนดค่าเหล่านี้ได้ และเนื่องจากข้อจำกัดนี้ โปรดอ้างอิงข้อจำกัด
แสดงใน
เอกสารอ้างอิง ANeuralNetworksMemory_createFromAHardwareBuffer
และทดสอบล่วงหน้าในอุปกรณ์เป้าหมายเพื่อให้มั่นใจว่ามีการคอมไพล์และการดำเนินการ
ที่ใช้ AHardwareBuffer
จะทำงานตามที่คาดไว้ โดยใช้
การกำหนดอุปกรณ์เพื่อระบุ Accelerator
หากต้องการอนุญาตให้รันไทม์ของ NNAPI เข้าถึงออบเจ็กต์ AHardwareBuffer
ให้สร้าง
ANeuralNetworksMemory
โดยการเรียกฟังก์ชัน
ฟังก์ชัน ANeuralNetworksMemory_createFromAHardwareBuffer
และการส่งในฟังก์ชัน
ออบเจ็กต์ AHardwareBuffer
ดังที่แสดงในตัวอย่างโค้ดต่อไปนี้
// Configure and create AHardwareBuffer object AHardwareBuffer_Desc desc = ... AHardwareBuffer* ahwb = nullptr; AHardwareBuffer_allocate(&desc, &ahwb); // Create ANeuralNetworksMemory from AHardwareBuffer ANeuralNetworksMemory* mem2 = NULL; ANeuralNetworksMemory_createFromAHardwareBuffer(ahwb, &mem2);
เมื่อ NNAPI ไม่ต้องการเข้าถึงออบเจ็กต์ AHardwareBuffer
อีกต่อไป ให้เพิ่มพื้นที่ว่าง
อินสแตนซ์ ANeuralNetworksMemory
ที่เกี่ยวข้อง:
ANeuralNetworksMemory_free(mem2);
หมายเหตุ:
- คุณสามารถใช้
AHardwareBuffer
เท่านั้นสำหรับบัฟเฟอร์ทั้งหมด คุณไม่สามารถใช้กับ พารามิเตอร์ARect
- รันไทม์ของ NNAPI จะไม่ล้างออก เพื่อบัฟเฟอร์ คุณต้องตรวจสอบว่าบัฟเฟอร์อินพุตและเอาต์พุต ก่อนกำหนดเวลาการดำเนินการ
- ไม่มีการสนับสนุนสำหรับ Sync Fence Descriptor
- สำหรับ
AHardwareBuffer
ที่มี รูปแบบเฉพาะผู้ให้บริการและบิตการใช้งาน จะขึ้นอยู่กับการใช้งานของผู้ให้บริการ เพื่อดูว่าลูกค้าหรือคนขับเป็นผู้รับผิดชอบในการล้าง แคช
รุ่น
โมเดลคือหน่วยพื้นฐานของการคำนวณใน NNAPI แต่ละโมเดลได้รับการกำหนดไว้ โดยตัวถูกดำเนินการและการดำเนินการอย่างน้อย 1 รายการ
ตัวถูกดำเนินการ
ตัวดำเนินการคือออบเจ็กต์ข้อมูลที่ใช้ในการกำหนดกราฟ ซึ่งรวมถึงอินพุต และเอาต์พุตของโมเดล ซึ่งเป็นโหนดระดับกลางที่มีข้อมูลที่ ไหลจากการดำเนินการหนึ่งไปยังอีกการดำเนินการ และค่าคงที่ที่ส่งผ่านไปยัง การดำเนินงานเหล่านี้
มีตัวถูกดำเนินการ 2 ประเภทที่สามารถเพิ่มลงในโมเดล NNAPI ได้แก่ สเกลาร์ และ tensors
สเกลาร์แสดงถึงค่าเดียว NNAPI รองรับค่าสเกลาร์ในบูลีน จุดลอยตัว 16 บิต, จุดลอยตัว 32 บิต, จำนวนเต็ม 32 บิต และไม่มีเครื่องหมาย รูปแบบจำนวนเต็ม 32 บิต
การดำเนินการส่วนใหญ่ใน NNAPI เกี่ยวข้องกับ Tensor Tensor คืออาร์เรย์ N มิติ NNAPI รองรับ tensor ที่มีจุดลอยตัว 16 บิต, จุดลอยตัว 32 บิต, 8 บิต Quantized, 16 บิตที่ควอนไตซ์, จำนวนเต็ม 32 บิต และ 8 บิต ค่าบูลีน
ตัวอย่างเช่น รูปที่ 3 หมายถึงโมเดลที่มีการดำเนินการ 2 อย่าง ได้แก่ การบวก ตามด้วยการคูณ โมเดลจะใช้ Tensor อินพุตและสร้าง 1 รายการ Tensor เอาต์พุต
![](https://developer.android.google.cn/static/ndk/images/nnapi/nnapi_operands.png?authuser=0000&hl=th)
โมเดลด้านบนมีตัวถูกดำเนินการ 7 ตัว ตัวถูกดำเนินการเหล่านี้จะระบุโดยปริยายโดย ดัชนีของลำดับที่เพิ่มลงในโมเดล ตัวถูกดำเนินการแรก ที่ถูกเพิ่มจะมีดัชนีเป็น 0 ดัชนีที่สองเป็น 1 เป็นต้น ตัวต่อตัว 1, 2, 3 และ 5 คือตัวถูกดำเนินการคงที่
ลำดับที่คุณเพิ่มตัวถูกดำเนินการไม่สำคัญ ตัวอย่างเช่น โมเดล ตัวถูกดำเนินการของเอาต์พุตอาจเป็นตัวถูกเพิ่มลงในตัวแรก ส่วนสำคัญคือการใช้ ค่าดัชนีถูกต้องเมื่ออ้างถึงตัวถูกดำเนินการ
ตัวดำเนินการมีหลายประเภท ซึ่งจะระบุเมื่อมีการเพิ่มลงในโมเดล
คุณใช้ตัวถูกดำเนินการเป็นทั้งอินพุตและเอาต์พุตของโมเดลไม่ได้
ตัวถูกดำเนินการทั้งหมดต้องเป็นอินพุตโมเดล ค่าคงที่ หรือตัวถูกดำเนินการเอาต์พุตของ หนึ่งการดำเนินการเท่านั้น
ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ตัวถูกดำเนินการได้ที่ ข้อมูลเพิ่มเติมเกี่ยวกับตัวถูกดำเนินการ
การทำงาน
การดำเนินการจะระบุการคำนวณที่จะดำเนินการ การดำเนินการแต่ละรายการประกอบด้วย ขององค์ประกอบเหล่านี้
- ประเภทการดำเนินการ (เช่น การบวก การคูณ Convolution)
- รายการดัชนีของตัวถูกดำเนินการที่การดำเนินการใช้สำหรับอินพุต และ
- รายการดัชนีของตัวถูกดำเนินการที่การดำเนินการใช้สำหรับเอาต์พุต
ลำดับในรายการเหล่านี้มีความสำคัญ โปรดดู เอกสารอ้างอิง NNAPI API สำหรับอินพุตที่คาดไว้ และเอาต์พุตของการดำเนินการแต่ละประเภท
คุณต้องเพิ่มตัวถูกดำเนินการที่การดำเนินการใช้หรือสร้างในโมเดล ก่อนเพิ่มการดำเนินการ
ลำดับที่คุณเพิ่มการดำเนินการไม่มีผล NNAPI อาศัย ทรัพยากร Dependency ที่กำหนดโดยกราฟการคำนวณของตัวถูกดำเนินการและการดำเนินการกับ กำหนดลำดับการดำเนินการ
การดำเนินการที่ NNAPI รองรับจะสรุปไว้ในตารางด้านล่าง
ปัญหาที่ทราบใน API ระดับ 28: เมื่อส่ง
ANEURALNETWORKS_TENSOR_QUANT8_ASYMM
Tensor ไปยัง
ANEURALNETWORKS_PAD
ซึ่งพร้อมใช้งานใน Android 9 (API ระดับ 28) ขึ้นไป
เอาต์พุตจาก NNAPI อาจไม่ตรงกับผลลัพธ์จากแมชชีนเลิร์นนิงในระดับที่สูงกว่า
เช่น เฟรมเวิร์ก
TensorFlow Lite คุณ
ควรที่จะผ่านเท่านั้น
ANEURALNETWORKS_TENSOR_FLOAT32
ปัญหาได้รับการแก้ไขแล้วใน Android 10 (API ระดับ 29) ขึ้นไป
สร้างโมเดล
ในตัวอย่างต่อไปนี้ เราสร้างโมเดลการดำเนินการ 2 แบบที่พบใน รูปที่ 3
หากต้องการสร้างโมเดล ให้ทำตามขั้นตอนต่อไปนี้
เรียกใช้
ANeuralNetworksModel_create()
เพื่อกำหนดโมเดลที่ว่างเปล่าANeuralNetworksModel* model = NULL; ANeuralNetworksModel_create(&model);
เพิ่มตัวถูกดำเนินการลงในโมเดลโดยการเรียกใช้
ANeuralNetworks_addOperand()
ประเภทข้อมูลจะกำหนดโดยใช้ANeuralNetworksOperandType
โครงสร้างข้อมูล// In our example, all our tensors are matrices of dimension [3][4] ANeuralNetworksOperandType tensor3x4Type; tensor3x4Type.type = ANEURALNETWORKS_TENSOR_FLOAT32; tensor3x4Type.scale = 0.f; // These fields are used for quantized tensors tensor3x4Type.zeroPoint = 0; // These fields are used for quantized tensors tensor3x4Type.dimensionCount = 2; uint32_t dims[2] = {3, 4}; tensor3x4Type.dimensions = dims;
// We also specify operands that are activation function specifiers ANeuralNetworksOperandType activationType; activationType.type = ANEURALNETWORKS_INT32; activationType.scale = 0.f; activationType.zeroPoint = 0; activationType.dimensionCount = 0; activationType.dimensions = NULL;
// Now we add the seven operands, in the same order defined in the diagram ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 0 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 1 ANeuralNetworksModel_addOperand(model, &activationType); // operand 2 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 3 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 4 ANeuralNetworksModel_addOperand(model, &activationType); // operand 5 ANeuralNetworksModel_addOperand(model, &tensor3x4Type); // operand 6สำหรับตัวถูกดำเนินการที่มีค่าคงที่ เช่น น้ำหนักและความลำเอียงที่ ที่ได้รับจากกระบวนการฝึกอบรม ให้ใช้
ANeuralNetworksModel_setOperandValue()
และANeuralNetworksModel_setOperandValueFromMemory()
ในตัวอย่างต่อไปนี้ เรากำหนดค่าคงที่จากไฟล์ข้อมูลการฝึก ที่สอดคล้องกับบัฟเฟอร์หน่วยความจำที่เราสร้างขึ้นในให้การเข้าถึง ข้อมูลการฝึกอบรม
// In our example, operands 1 and 3 are constant tensors whose values were // established during the training process const int sizeOfTensor = 3 * 4 * 4; // The formula for size calculation is dim0 * dim1 * elementSize ANeuralNetworksModel_setOperandValueFromMemory(model, 1, mem1, 0, sizeOfTensor); ANeuralNetworksModel_setOperandValueFromMemory(model, 3, mem1, sizeOfTensor, sizeOfTensor);
// We set the values of the activation operands, in our example operands 2 and 5 int32_t noneValue = ANEURALNETWORKS_FUSED_NONE; ANeuralNetworksModel_setOperandValue(model, 2, &noneValue, sizeof(noneValue)); ANeuralNetworksModel_setOperandValue(model, 5, &noneValue, sizeof(noneValue));สำหรับแต่ละการดำเนินการในกราฟมีทิศทางที่คุณต้องการคำนวณ ให้ใส่ฟิลด์ ไปยังโมเดลของคุณโดยเรียก
ANeuralNetworksModel_addOperation()
แอปจะต้องระบุข้อมูลต่อไปนี้เป็นพารามิเตอร์ในการเรียกนี้
- ประเภทการดำเนินการ
- จำนวนค่าอินพุต
- อาร์เรย์ของดัชนีสำหรับตัวถูกดำเนินการของอินพุต
- จำนวนค่าเอาต์พุต
- อาร์เรย์ของดัชนีสำหรับตัวถูกดำเนินการของเอาต์พุต
โปรดทราบว่าไม่สามารถใช้ตัวถูกดำเนินการได้ทั้งสำหรับอินพุตและเอาต์พุตของ การดำเนินการ
// We have two operations in our example // The first consumes operands 1, 0, 2, and produces operand 4 uint32_t addInputIndexes[3] = {1, 0, 2}; uint32_t addOutputIndexes[1] = {4}; ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_ADD, 3, addInputIndexes, 1, addOutputIndexes);
// The second consumes operands 3, 4, 5, and produces operand 6 uint32_t multInputIndexes[3] = {3, 4, 5}; uint32_t multOutputIndexes[1] = {6}; ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_MUL, 3, multInputIndexes, 1, multOutputIndexes);ระบุตัวถูกดำเนินการที่โมเดลควรถือเป็นอินพุตและเอาต์พุตโดย การเรียกฟังก์ชัน
ANeuralNetworksModel_identifyInputsAndOutputs()
// Our model has one input (0) and one output (6) uint32_t modelInputIndexes[1] = {0}; uint32_t modelOutputIndexes[1] = {6}; ANeuralNetworksModel_identifyInputsAndOutputs(model, 1, modelInputIndexes, 1 modelOutputIndexes);
(ไม่บังคับ) ระบุว่า
ANEURALNETWORKS_TENSOR_FLOAT32
ได้รับอนุญาตให้คำนวณด้วยช่วงหรือความแม่นยำต่ำเท่ากับ รูปแบบจุดลอยตัว 16 บิต IEEE 754 ด้วยการเรียกANeuralNetworksModel_relaxComputationFloat32toFloat16()
โทร
ANeuralNetworksModel_finish()
เพื่อสรุปการกำหนดโมเดลของคุณ หากไม่มีข้อผิดพลาด แสดงผลรหัสผลลัพธ์ของANEURALNETWORKS_NO_ERROR
ANeuralNetworksModel_finish(model);
เมื่อสร้างโมเดลแล้ว คุณสามารถคอมไพล์โมเดลได้ไม่จำกัดจำนวนครั้งและสั่งการแต่ละโมเดล คอมไพล์ได้ไม่จำกัดจำนวนครั้ง
ควบคุมโฟลว์
ในการรวมขั้นตอนการควบคุมไว้ในโมเดล NNAPI ให้ทำดังนี้
สร้างกราฟย่อยการดำเนินการที่เกี่ยวข้อง (
then
และelse
กราฟย่อย สำหรับคำสั่งIF
,condition
และbody
กราฟย่อยสำหรับWHILE
วนซ้ำ) เป็นโมเดลANeuralNetworksModel*
แบบสแตนด์อโลนANeuralNetworksModel* thenModel = makeThenModel(); ANeuralNetworksModel* elseModel = makeElseModel();
สร้างตัวถูกดำเนินการที่อ้างอิงถึงโมเดลเหล่านั้นภายในโมเดลที่มีส่วน ควบคุมโฟลว์:
ANeuralNetworksOperandType modelType = { .type = ANEURALNETWORKS_MODEL, }; ANeuralNetworksModel_addOperand(model, &modelType); // kThenOperandIndex ANeuralNetworksModel_addOperand(model, &modelType); // kElseOperandIndex ANeuralNetworksModel_setOperandValueFromModel(model, kThenOperandIndex, &thenModel); ANeuralNetworksModel_setOperandValueFromModel(model, kElseOperandIndex, &elseModel);
เพิ่มการดำเนินการขั้นตอนการควบคุมดังนี้
uint32_t inputs[] = {kConditionOperandIndex, kThenOperandIndex, kElseOperandIndex, kInput1, kInput2, kInput3}; uint32_t outputs[] = {kOutput1, kOutput2}; ANeuralNetworksModel_addOperation(model, ANEURALNETWORKS_IF, std::size(inputs), inputs, std::size(output), outputs);
การรวบรวม
ขั้นตอนการคอมไพล์จะเป็นตัวกำหนดโปรเซสเซอร์ที่โมเดลของคุณจะทำงาน และขอให้คนขับที่เกี่ยวข้องเตรียมพร้อมสำหรับการปฏิบัติการ การดำเนินการนี้อาจ รวมการสร้างรหัสของเครื่องสำหรับโปรเซสเซอร์โมเดลของคุณโดยเฉพาะ จะทำงานต่อ
หากต้องการคอมไพล์โมเดล ให้ทำตามขั้นตอนต่อไปนี้
เรียกใช้
ANeuralNetworksCompilation_create()
เพื่อสร้างอินสแตนซ์การคอมไพล์ใหม่// Compile the model ANeuralNetworksCompilation* compilation; ANeuralNetworksCompilation_create(model, &compilation);
นอกจากนี้ คุณยังใช้การกำหนดอุปกรณ์เพื่อ เลือกอุปกรณ์ที่จะเรียกใช้
คุณเลือกควบคุมการเปลี่ยนรันไทม์ระหว่างพลังงานแบตเตอรี่ได้ และการใช้งานได้อย่างรวดเร็ว คุณสามารถทำได้โดยการโทร
ANeuralNetworksCompilation_setPreference()
// Ask to optimize for low power consumption ANeuralNetworksCompilation_setPreference(compilation, ANEURALNETWORKS_PREFER_LOW_POWER);
ค่ากำหนดที่คุณสามารถระบุได้มีดังนี้
ANEURALNETWORKS_PREFER_LOW_POWER
: ควรเรียกใช้ในลักษณะที่ช่วยลดการใช้แบตเตอรี่ให้เหลือน้อยที่สุด ช่วยได้มาก สำหรับการรวบรวมที่มีการดำเนินการบ่อยครั้งANEURALNETWORKS_PREFER_FAST_SINGLE_ANSWER
: หากต้องการให้ระบบแสดงคำตอบข้อเดียวโดยเร็วที่สุด แม้ว่าจะเป็นสาเหตุก็ตาม ใช้พลังงานมากขึ้น โดยตัวเลือกนี้คือค่าเริ่มต้นANEURALNETWORKS_PREFER_SUSTAINED_SPEED
: เพิ่มประสิทธิภาพอัตราการส่งข้อมูลของเฟรมต่อเนื่อง เช่น เมื่อ ประมวลผลเฟรมต่อเนื่องที่มาจากกล้อง
คุณสามารถเลือกตั้งค่าการแคชการรวบรวมได้โดยการเรียกใช้
ANeuralNetworksCompilation_setCaching
// Set up compilation caching ANeuralNetworksCompilation_setCaching(compilation, cacheDir, token);
ใช้
getCodeCacheDir()
สำหรับcacheDir
token
ที่ระบุต้องไม่ซ้ำกันสำหรับแต่ละโมเดลภายใน แอปพลิเคชันสรุปคำจำกัดความของการรวบรวมคลิปโดยการเรียกใช้
ANeuralNetworksCompilation_finish()
หากไม่มีข้อผิดพลาด ฟังก์ชันนี้จะแสดงรหัสผลลัพธ์ของANEURALNETWORKS_NO_ERROR
ANeuralNetworksCompilation_finish(compilation);
การค้นหาและการกำหนดอุปกรณ์
NNAPI มีให้บริการสำหรับอุปกรณ์ Android ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไป ฟังก์ชันที่ช่วยให้ไลบรารีและแอปของเฟรมเวิร์กแมชชีนเลิร์นนิงได้รับ ข้อมูลเกี่ยวกับอุปกรณ์ที่ใช้ได้และระบุอุปกรณ์ที่จะใช้ การให้ข้อมูลเกี่ยวกับอุปกรณ์ที่มีอยู่ช่วยให้แอป เวอร์ชันจริงของไดรเวอร์ที่พบในอุปกรณ์เพื่อหลีกเลี่ยงที่ทราบ ไม่เข้ากัน โดยทำให้แอปสามารถระบุได้ว่าจะใช้อุปกรณ์ใด ใช้งานส่วนต่างๆ ของโมเดล แอปสามารถเพิ่มประสิทธิภาพสำหรับ Android อุปกรณ์ที่นำไปใช้งาน
การค้นหาอุปกรณ์
ใช้
ANeuralNetworks_getDeviceCount
เพื่อดูจำนวนอุปกรณ์ที่ใช้ได้ สำหรับแต่ละอุปกรณ์ ให้ใช้
ANeuralNetworks_getDevice
เพื่อตั้งค่าอินสแตนซ์ ANeuralNetworksDevice
เป็นการอ้างอิงไปยังอุปกรณ์นั้น
เมื่อมีข้อมูลอ้างอิงอุปกรณ์แล้ว คุณก็สามารถดูข้อมูลเพิ่มเติมเกี่ยวกับ อุปกรณ์นั้นโดยใช้ฟังก์ชันต่อไปนี้
ANeuralNetworksDevice_getFeatureLevel
ANeuralNetworksDevice_getName
ANeuralNetworksDevice_getType
ANeuralNetworksDevice_getVersion
การกำหนดอุปกรณ์
ใช้
ANeuralNetworksModel_getSupportedOperationsForDevices
เพื่อค้นหาการดำเนินการของโมเดลที่เรียกใช้ในอุปกรณ์ที่เจาะจงได้
หากต้องการควบคุม Accelerator ที่จะใช้ในการดำเนินการ ให้เรียกใช้
ANeuralNetworksCompilation_createForDevices
แทน ANeuralNetworksCompilation_create
ใช้ออบเจ็กต์ ANeuralNetworksCompilation
ที่ได้มาตามปกติ
ฟังก์ชันจะแสดงข้อผิดพลาดหากโมเดลที่ระบุมีการดำเนินการที่
ไม่รองรับในอุปกรณ์ที่เลือก
หากระบุอุปกรณ์หลายเครื่อง รันไทม์จะทำหน้าที่กระจายข้อมูล การทำงานในอุปกรณ์ต่างๆ
เช่นเดียวกับอุปกรณ์อื่นๆ การใช้งาน CPU NNAPI จะแสดงด้วยองค์ประกอบ
ANeuralNetworksDevice
ที่ชื่อ nnapi-reference
และเป็นประเภท
ANEURALNETWORKS_DEVICE_TYPE_CPU
เมื่อโทร
ANeuralNetworksCompilation_createForDevices
, การใช้งาน CPU ไม่ได้
ซึ่งใช้สำหรับจัดการกรณีความล้มเหลวในการคอมไพล์โมเดลและการดำเนินการ
แอปพลิเคชันมีหน้าที่รับผิดชอบในการแบ่งพาร์ติชันโมเดลเป็นโมเดลย่อยที่
สามารถทำงานในอุปกรณ์ที่ระบุ แอปพลิเคชันที่ไม่จำเป็นต้องทำด้วยตนเอง
ควรจะยังคงเรียกการแบ่งพาร์ติชัน
ANeuralNetworksCompilation_create
ให้ใช้อุปกรณ์ที่มีอยู่ทั้งหมด (รวมถึง CPU) เพื่อเร่งความเร็ว
โมเดล หากอุปกรณ์ที่คุณระบุรองรับโมเดลได้ไม่สมบูรณ์
โดยใช้ ANeuralNetworksCompilation_createForDevices
ANEURALNETWORKS_BAD_DATA
การแบ่งพาร์ติชันโมเดล
เมื่อมีอุปกรณ์หลายเครื่องสำหรับโมเดลนี้ รันไทม์ของ NNAPI
กระจายงานไปยังทุกอุปกรณ์ ตัวอย่างเช่น หากมีอุปกรณ์มากกว่า 1 เครื่อง
ให้กับ ANeuralNetworksCompilation_createForDevices
ทุกค่าที่ระบุ
จะได้รับการพิจารณาเมื่อจัดสรรงาน โปรดทราบว่าหากอุปกรณ์ CPU
ไม่อยู่ในรายชื่อนี้ ระบบจะปิดการดำเนินการของ CPU เมื่อใช้ ANeuralNetworksCompilation_create
จะมีการพิจารณาอุปกรณ์ที่ใช้ได้ทั้งหมด รวมถึง CPU ด้วย
การกระจายนี้ทำได้โดยการเลือกจากรายการอุปกรณ์ที่พร้อมใช้งาน
การดำเนินการในโมเดล อุปกรณ์ที่สนับสนุนการทำงาน และ
การประกาศประสิทธิภาพที่ดีที่สุด กล่าวคือ เวลาที่มีการดำเนินการรวดเร็วที่สุด หรือ
ใช้พลังงานต่ำสุด โดยขึ้นอยู่กับค่ากำหนดการดำเนินการที่ระบุโดย
ไคลเอ็นต์ อัลกอริทึมการแบ่งพาร์ติชันนี้ไม่นับว่าเป็นไปได้
ความไร้ประสิทธิภาพอันเกิดจาก IO ระหว่างโปรเซสเซอร์ต่างๆ
การระบุโปรเซสเซอร์หลายรายการ (อย่างชัดเจนเมื่อใช้
ANeuralNetworksCompilation_createForDevices
หรือโดยนัยโดยใช้
ANeuralNetworksCompilation_create
) คุณจำเป็นต้องสร้างโปรไฟล์ผลลัพธ์
แอปพลิเคชัน
หากต้องการทำความเข้าใจวิธีที่ NNAPI แบ่งพาร์ติชันโมเดล ให้ดูที่
บันทึก Android สำหรับข้อความ (ที่ระดับ INFO ที่มีแท็ก ExecutionPlan
):
ModelBuilder::findBestDeviceForEachOperation(op-name): device-index
op-name
คือชื่อที่สื่อความหมายของการดำเนินการในกราฟ และ
device-index
คือดัชนีของอุปกรณ์ที่ต้องการในรายการอุปกรณ์
รายการนี้เป็นอินพุตที่ป้อนให้กับ ANeuralNetworksCompilation_createForDevices
หรือถ้าใช้ ANeuralNetworksCompilation_createForDevices
ให้แสดงรายการอุปกรณ์
แสดงผลเมื่อทำซ้ำในอุปกรณ์ทั้งหมดที่ใช้ ANeuralNetworks_getDeviceCount
และ
ANeuralNetworks_getDevice
ข้อความ (ที่ระดับ INFO ที่มีแท็ก ExecutionPlan
):
ModelBuilder::partitionTheWork: only one best device: device-name
ข้อความนี้แสดงว่ามีการเร่งกราฟทั้งกราฟในอุปกรณ์แล้ว
device-name
การลงมือปฏิบัติ
ขั้นตอนการดำเนินการจะใช้โมเดลกับชุดอินพุตและจัดเก็บ เอาต์พุตไปยังบัฟเฟอร์ผู้ใช้หรือพื้นที่หน่วยความจำอย่างน้อย 1 รายการซึ่งแอปของคุณ ที่จัดสรรไว้
ในการใช้งานโมเดลที่คอมไพล์แล้ว ให้ทำตามขั้นตอนต่อไปนี้
เรียกใช้
ANeuralNetworksExecution_create()
เพื่อสร้างอินสแตนซ์การดำเนินการใหม่// Run the compiled model against a set of inputs ANeuralNetworksExecution* run1 = NULL; ANeuralNetworksExecution_create(compilation, &run1);
ระบุตำแหน่งที่แอปอ่านค่าอินพุตสำหรับการคำนวณ แอปของคุณ อ่านค่าอินพุตจากบัฟเฟอร์ผู้ใช้หรือพื้นที่หน่วยความจำที่จัดสรรได้ โดยการโทร
ANeuralNetworksExecution_setInput()
หรือANeuralNetworksExecution_setInputFromMemory()
ตามลำดับ// Set the single input to our sample model. Since it is small, we won't use a memory buffer float32 myInput[3][4] = { ...the data... }; ANeuralNetworksExecution_setInput(run1, 0, NULL, myInput, sizeof(myInput));
ระบุตำแหน่งที่แอปเขียนค่าเอาต์พุต แอปของคุณสามารถเขียนค่าเอาต์พุตไปยัง บัฟเฟอร์ผู้ใช้หรือพื้นที่หน่วยความจำที่จัดสรรไว้ โดยการเรียกใช้
ANeuralNetworksExecution_setOutput()
หรือANeuralNetworksExecution_setOutputFromMemory()
ตามลำดับ// Set the output float32 myOutput[3][4]; ANeuralNetworksExecution_setOutput(run1, 0, NULL, myOutput, sizeof(myOutput));
กำหนดเวลาการดำเนินการเพื่อเริ่มต้น โดยเรียกใช้
ANeuralNetworksExecution_startCompute()
หากไม่มีข้อผิดพลาด ฟังก์ชันนี้จะแสดงรหัสผลลัพธ์ของANEURALNETWORKS_NO_ERROR
// Starts the work. The work proceeds asynchronously ANeuralNetworksEvent* run1_end = NULL; ANeuralNetworksExecution_startCompute(run1, &run1_end);
โทรหา
ANeuralNetworksEvent_wait()
เพื่อรอให้การดำเนินการเสร็จสิ้น หากการดำเนินการคือ สำเร็จ ฟังก์ชันนี้ส่งคืนรหัสผลลัพธ์ของANEURALNETWORKS_NO_ERROR
ระบบสามารถดําเนินการรอในชุดข้อความอื่นที่ไม่ใช่เทรดที่เริ่มต้นการดําเนินการ// For our example, we have no other work to do and will just wait for the completion ANeuralNetworksEvent_wait(run1_end); ANeuralNetworksEvent_free(run1_end); ANeuralNetworksExecution_free(run1);
หรือคุณจะใช้ชุดอินพุตอื่นกับโมเดลที่คอมไพล์ได้โดย โดยใช้อินสแตนซ์การคอมไพล์เดียวกันเพื่อสร้าง
ANeuralNetworksExecution
อินสแตนซ์// Apply the compiled model to a different set of inputs ANeuralNetworksExecution* run2; ANeuralNetworksExecution_create(compilation, &run2); ANeuralNetworksExecution_setInput(run2, ...); ANeuralNetworksExecution_setOutput(run2, ...); ANeuralNetworksEvent* run2_end = NULL; ANeuralNetworksExecution_startCompute(run2, &run2_end); ANeuralNetworksEvent_wait(run2_end); ANeuralNetworksEvent_free(run2_end); ANeuralNetworksExecution_free(run2);
การดำเนินการแบบซิงโครนัส
การดำเนินการแบบไม่พร้อมกันต้องใช้เวลาในการสร้างและซิงค์ข้อมูลชุดข้อความ นอกจากนี้ เวลาในการตอบสนองอาจมีความผันผวนอย่างมาก โดยมีระยะเวลา ความล่าช้าสูงสุด 500 ไมโครวินาทีนับจากที่มีการแจ้งเตือนชุดข้อความ หรือ ทำงานอีกครั้ง และในที่สุดแล้วก็จะเชื่อมโยงกับแกน CPU
หากต้องการปรับปรุงเวลาในการตอบสนอง คุณสามารถกำหนดให้แอปพลิเคชันทำการโหลดแบบซิงโครนัสแทนได้
การเรียกอนุมานไปยังรันไทม์ ระบบจะเรียกการเรียกดังกล่าวอีกครั้งเมื่อการอนุมาน
ได้รับการดำเนินการโดยสมบูรณ์ แทนที่จะส่งกลับเมื่อเริ่มมีการอนุมาน แทน
ของการโทร
ANeuralNetworksExecution_startCompute
สำหรับการเรียกการอนุมานแบบไม่พร้อมกันไปยังรันไทม์ การเรียกใช้แอปพลิเคชัน
ANeuralNetworksExecution_compute
เพื่อทำการเรียกแบบซิงโครนัสกับรันไทม์ การโทรถึง
ANeuralNetworksExecution_compute
ไม่ได้รับ ANeuralNetworksEvent
และ
ไม่ได้จับคู่กับการโทรไปยัง ANeuralNetworksEvent_wait
การดำเนินการแบบทันที
NNAPI รองรับภาพถ่ายอัจฉริยะในอุปกรณ์ Android ที่ใช้ Android 10 (API ระดับ 29) ขึ้นไป
ที่ดำเนินการผ่าน
ANeuralNetworksBurst
ออบเจ็กต์ การดำเนินการแบบทันทีเป็นลำดับการดำเนินการในคอมไพล์เดียวกัน
ที่เกิดขึ้นต่อเนื่องกันอย่างรวดเร็ว เช่น เฟรมที่ทำงานบนเฟรมกล้อง
บันทึกเสียงหรือตัวอย่างเสียงต่อเนื่อง การใช้ออบเจ็กต์ ANeuralNetworksBurst
รายการอาจส่งผล
ส่งผลให้ดำเนินการได้รวดเร็ว เนื่องจากจะบ่งชี้ถึงตัวเร่งความเร็วว่าทรัพยากรต่างๆ
มาใช้ซ้ำได้ระหว่างการดำเนินการ และ Accelerator ควรคงอยู่
สถานะประสิทธิภาพสูงในช่วงที่ถ่ายภาพอัจฉริยะ
ANeuralNetworksBurst
ทำให้เกิดการเปลี่ยนแปลงเพียงเล็กน้อยในการดำเนินการตามปกติ
เส้นทาง คุณสร้างภาพถ่ายอัจฉริยะโดยใช้
ANeuralNetworksBurst_create
ดังที่แสดงในข้อมูลโค้ดต่อไปนี้
// Create burst object to be reused across a sequence of executions ANeuralNetworksBurst* burst = NULL; ANeuralNetworksBurst_create(compilation, &burst);
การดำเนินการแบบต่อเนื่องจะเป็นแบบพร้อมกัน อย่างไรก็ตาม แทนที่จะใช้
ANeuralNetworksExecution_compute
ในการอนุมานแต่ละรายการ คุณจะต้องจับคู่
ANeuralNetworksExecution
วัตถุที่มี ANeuralNetworksBurst
เดียวกันในการเรียกฟังก์ชัน
ANeuralNetworksExecution_burstCompute
// Create and configure first execution object // ... // Execute using the burst object ANeuralNetworksExecution_burstCompute(execution1, burst); // Use results of first execution and free the execution object // ... // Create and configure second execution object // ... // Execute using the same burst object ANeuralNetworksExecution_burstCompute(execution2, burst); // Use results of second execution and free the execution object // ...
ทำให้ออบเจ็กต์ ANeuralNetworksBurst
เป็นอิสระด้วย
ANeuralNetworksBurst_free
เมื่อไม่จำเป็นต้องใช้แล้ว
// Cleanup ANeuralNetworksBurst_free(burst);
คิวคำสั่งแบบไม่พร้อมกันและการดำเนินการแบบ Fenced
ใน Android 11 ขึ้นไป NNAPI รองรับวิธีกำหนดเวลาเพิ่มเติม
การดำเนินการแบบอะซิงโครนัสผ่าน
ANeuralNetworksExecution_startComputeWithDependencies()
เมื่อคุณใช้วิธีนี้ การดำเนินการจะรอข้อมูลต่อไปนี้ทั้งหมด
ที่จะส่งสัญญาณก่อนเริ่มการประเมิน เมื่อการดำเนินการได้
เสร็จสมบูรณ์ และเอาต์พุตพร้อมใช้งานแล้ว เหตุการณ์ที่ส่งกลับคือ
ได้รับสัญญาณ
กิจกรรมอาจมีการสนับสนุนโดย
ซิงค์ Fence คุณ
ต้องเรียก
ANeuralNetworksEvent_wait()
เพื่อรอเหตุการณ์และกู้คืนทรัพยากรที่การดำเนินการใช้ไป คุณ
สามารถนำเข้าขอบเขตการซิงค์ไปยังออบเจ็กต์เหตุการณ์ได้โดยใช้
ANeuralNetworksEvent_createFromSyncFenceFd()
และคุณสามารถส่งออกขอบเขตการซิงค์จากออบเจ็กต์เหตุการณ์ได้โดยใช้
ANeuralNetworksEvent_getSyncFenceFd()
เอาต์พุตที่มีขนาดแบบไดนามิก
เพื่อรองรับโมเดลที่ขนาดของเอาต์พุตขึ้นอยู่กับอินพุต
ซึ่งก็คือข้อมูลที่ไม่สามารถระบุขนาดได้ในการดำเนินการโมเดล
เวลา—ใช้
ANeuralNetworksExecution_getOutputOperandRank
และ
ANeuralNetworksExecution_getOutputOperandDimensions
ตัวอย่างโค้ดต่อไปนี้แสดงวิธีดำเนินการ
// Get the rank of the output uint32_t myOutputRank = 0; ANeuralNetworksExecution_getOutputOperandRank(run1, 0, &myOutputRank); // Get the dimensions of the output std::vector<uint32_t> myOutputDimensions(myOutputRank); ANeuralNetworksExecution_getOutputOperandDimensions(run1, 0, myOutputDimensions.data());
ทำความสะอาดข้อมูล
ขั้นตอนการล้างข้อมูลจะช่วยจัดการกับการปลดทรัพยากรภายในที่ใช้สำหรับ การคำนวณ
// Cleanup ANeuralNetworksCompilation_free(compilation); ANeuralNetworksModel_free(model); ANeuralNetworksMemory_free(mem1);
การจัดการข้อผิดพลาดและ CPU สำรอง
ถ้าเกิดข้อผิดพลาดระหว่างการแบ่งพาร์ติชัน ถ้าไดรเวอร์ไม่สามารถคอมไพล์ (ส่วนของ a) หรือหากไดรเวอร์ไม่สามารถดำเนินการกับโมเดลที่คอมไพล์แล้ว NNAPI อาจกลับไปใช้ CPU ของตนเองมากกว่า 1 รายการ การดำเนินงาน
หากไคลเอ็นต์ NNAPI มีการดำเนินการเวอร์ชันที่เพิ่มประสิทธิภาพ (เช่น เช่น TFLite) การปิดใช้งานตัวเลือก CPU สำรองและ จัดการความล้มเหลวด้วยการดำเนินการเพิ่มประสิทธิภาพของไคลเอ็นต์
ใน Android 10 หากทำการคอมไพล์โดยใช้
ANeuralNetworksCompilation_createForDevices
จากนั้นระบบจะปิดใช้ CPU สำรอง
ใน Android P การดำเนินการ NNAPI จะกลับไปที่ CPU หากการดำเนินการในไดรเวอร์ล้มเหลว
เหตุการณ์เช่นนี้จะเป็นจริงใน Android 10 เช่นกันเมื่อ ANeuralNetworksCompilation_create
กว่า ANeuralNetworksCompilation_createForDevices
การดำเนินการครั้งแรกจะย้อนกลับสำหรับพาร์ติชันเดี่ยวดังกล่าว และหากยังคง ไม่สำเร็จ ระบบจะลองใช้โมเดลทั้งโมเดลบน CPU อีกครั้ง
หากการแบ่งพาร์ติชันหรือการคอมไพล์ล้มเหลว ระบบจะลองใช้ทั้งโมเดลบน CPU
แต่อาจมีบางกรณีที่ CPU ไม่รองรับการดำเนินการบางอย่าง การรวบรวมหรือดำเนินการจะล้มเหลวแทนที่จะย้อนกลับ
แม้ว่าจะปิดใช้การสำรอง CPU ไปแล้ว แต่อาจมีการดำเนินการต่างๆ ในโมเดล
ที่กำหนดไว้บน CPU หาก CPU อยู่ในรายการโปรเซสเซอร์ที่ให้มา
เป็น ANeuralNetworksCompilation_createForDevices
และเป็น
ประเภทเดียวที่เลือก
ผู้ประมวลผลข้อมูลที่สนับสนุนการดำเนินการเหล่านั้น หรือเป็นผู้ประมวลผลข้อมูลที่กล่าวอ้างว่าดีที่สุด
ประสิทธิภาพสำหรับการดำเนินการเหล่านั้น ระบบจะเลือกเป็นข้อมูลหลัก (ไม่ใช่วิดีโอสำรอง)
ผู้ดำเนินการ
หากต้องการตรวจสอบว่าไม่มีการดำเนินการของ CPU ให้ใช้ ANeuralNetworksCompilation_createForDevices
ขณะที่ยกเว้น nnapi-reference
ในรายการอุปกรณ์
เริ่มตั้งแต่ Android P คุณจะปิดใช้วิดีโอสำรองในเวลาดำเนินการได้ที่
บิลด์ DEBUG โดยการตั้งค่าพร็อพเพอร์ตี้ debug.nn.partition
เป็น 2
โดเมนของหน่วยความจำ
ใน Android 11 ขึ้นไป NNAPI รองรับโดเมนหน่วยความจำที่มีตัวจัดสรร สำหรับความทรงจำที่ไม่ชัดเจน ซึ่งช่วยให้แอปพลิเคชันส่งผ่านการเชื่อมต่อเฉพาะอุปกรณ์ได้ หน่วยความจำในการดำเนินการต่างๆ เพื่อให้ NNAPI ไม่คัดลอกหรือเปลี่ยนรูปแบบข้อมูล โดยไม่จำเป็นเมื่อมีการดำเนินการติดต่อกันบนไดรเวอร์เดียวกัน
ฟีเจอร์โดเมนหน่วยความจำมีไว้สำหรับ Tensor ที่ส่วนใหญ่เป็นฟีเจอร์ภายใน ผู้ขับรถและไม่จําเป็นต้องเข้าถึงฝั่งไคลเอ็นต์บ่อยๆ ตัวอย่างของ Tensor ดังกล่าวรวมถึง Tensor สถานะในโมเดลลำดับ สำหรับ Tensor ที่ต้องการ การเข้าถึง CPU บ่อยครั้งในฝั่งไคลเอ็นต์ โปรดใช้พูลหน่วยความจำที่ใช้ร่วมกันแทน
หากต้องการจัดสรรหน่วยความจำที่คลุมเครือ ให้ทำตามขั้นตอนต่อไปนี้
เรียกใช้
ANeuralNetworksMemoryDesc_create()
เพื่อสร้างข้อบ่งชี้หน่วยความจำใหม่:// Create a memory descriptor ANeuralNetworksMemoryDesc* desc; ANeuralNetworksMemoryDesc_create(&desc);
ระบุบทบาทอินพุตและเอาต์พุตที่ต้องการทั้งหมดด้วยการเรียกใช้
ANeuralNetworksMemoryDesc_addInputRole()
และANeuralNetworksMemoryDesc_addOutputRole()
// Specify that the memory may be used as the first input and the first output // of the compilation ANeuralNetworksMemoryDesc_addInputRole(desc, compilation, 0, 1.0f); ANeuralNetworksMemoryDesc_addOutputRole(desc, compilation, 0, 1.0f);
(ไม่บังคับ) ระบุขนาดหน่วยความจำโดยการเรียกใช้
ANeuralNetworksMemoryDesc_setDimensions()
// Specify the memory dimensions uint32_t dims[] = {3, 4}; ANeuralNetworksMemoryDesc_setDimensions(desc, 2, dims);
สรุปคำจำกัดความข้อบ่งชี้โดยการเรียก
ANeuralNetworksMemoryDesc_finish()
ANeuralNetworksMemoryDesc_finish(desc);
จัดสรรความทรงจำได้มากเท่าที่ต้องการโดยการส่งข้อบ่งชี้ไปยัง
ANeuralNetworksMemory_createFromDesc()
// Allocate two opaque memories with the descriptor ANeuralNetworksMemory* opaqueMem; ANeuralNetworksMemory_createFromDesc(desc, &opaqueMem);
เพิ่มพื้นที่ว่างในข้อบ่งชี้หน่วยความจำเมื่อไม่ต้องการใช้งานแล้ว
ANeuralNetworksMemoryDesc_free(desc);
ไคลเอ็นต์จะใช้ออบเจ็กต์ ANeuralNetworksMemory
ที่สร้างขึ้นได้เฉพาะกับ
ANeuralNetworksExecution_setInputFromMemory()
หรือ
ANeuralNetworksExecution_setOutputFromMemory()
ตามบทบาท
ที่ระบุในออบเจ็กต์ ANeuralNetworksMemoryDesc
ออฟเซ็ตและความยาว
อาร์กิวเมนต์ต้องตั้งค่าเป็น 0 แสดงว่าใช้หน่วยความจำทั้งหมด ลูกค้า
อาจตั้งค่าหรือแยกเนื้อหาของหน่วยความจำอย่างชัดเจนโดยใช้
ANeuralNetworksMemory_copy()
คุณสามารถสร้างความทรงจำแบบทึบแสงด้วยบทบาทของมิติข้อมูลหรืออันดับที่ไม่ได้ระบุ
ในกรณีดังกล่าว การสร้างหน่วยความจำอาจล้มเหลวโดยมี
ANEURALNETWORKS_OP_FAILED
หากไม่รองรับโดยเครือข่ายพื้นฐาน
คนขับ ขอแนะนำให้ไคลเอ็นต์ใช้ตรรกะสำรองโดยการจัดสรร
บัฟเฟอร์ขนาดใหญ่เพียงพอที่ขับเคลื่อนโดย Ashmem หรือ BLOB-mode AHardwareBuffer
เมื่อ NNAPI ไม่ต้องการเข้าถึงออบเจ็กต์หน่วยความจำที่ทึบแสงอีกต่อไป ให้เพิ่มพื้นที่ว่าง
อินสแตนซ์ ANeuralNetworksMemory
ที่เกี่ยวข้อง:
ANeuralNetworksMemory_free(opaqueMem);
วัดประสิทธิภาพ
คุณสามารถประเมินประสิทธิภาพของแอปได้โดยการวัดเวลาดำเนินการหรือตาม การสร้างโปรไฟล์
เวลาดำเนินการ
หากต้องการกำหนดเวลาดำเนินการทั้งหมดผ่านรันไทม์ ให้ใช้
API การดำเนินการแบบซิงโครนัสและวัดเวลาที่เรียกใช้ เมื่อคุณ
ต้องการกำหนดเวลาทั้งหมดในการดำเนินการผ่านซอฟต์แวร์ในระดับที่ต่ำลง
คุณสามารถใช้
ANeuralNetworksExecution_setMeasureTiming
และ
ANeuralNetworksExecution_getDuration
เพื่อรับ:
- เวลาในการดำเนินการใน Accelerator (ไม่ใช่ในไดรเวอร์ ซึ่งทำงานบนโฮสต์ ผู้ประมวลผลข้อมูล)
- เวลาดำเนินการในคนขับ รวมถึงเวลาบน Accelerator
เวลาดำเนินการในไดรเวอร์ไม่รวมโอเวอร์เฮด เช่น เวลารันไทม์ และ IPC ที่จำเป็นสำหรับรันไทม์ในการสื่อสารกับไดรเวอร์
API เหล่านี้จะวัดระยะเวลาระหว่างงานที่ส่งและทำงานที่ทำเสร็จแล้ว กิจกรรม แทนที่จะเป็นเวลาที่คนขับรถหรือพนักงานเร่งทุ่มเทเวลาให้กับการจัดกิจกรรม ของการอนุมาน ซึ่งอาจถูกขัดจังหวะโดยการเปลี่ยนบริบท
ตัวอย่างเช่น หากการอนุมานเลข 1 เริ่มขึ้น ไดรเวอร์ก็หยุดงานเพื่อดำเนินการ อนุมานที่ 2 จะดำเนินการต่อ และเสร็จสิ้นการอนุมาน 1 ซึ่งเป็นเวลาดำเนินการสำหรับ อนุมาน 1 จะรวมเวลาที่งานหยุดเพื่อดำเนินการอนุมาน 2
ข้อมูลช่วงเวลานี้อาจมีประโยชน์สำหรับการติดตั้งใช้งานจริง สำหรับรวบรวมข้อมูลทางไกลสำหรับการใช้งานแบบออฟไลน์ คุณสามารถใช้ข้อมูลเวลาเพื่อ แก้ไขแอปเพื่อให้มีประสิทธิภาพสูงขึ้น
เมื่อใช้ฟังก์ชันนี้ โปรดคำนึงถึงสิ่งต่อไปนี้
- การรวบรวมข้อมูลเวลาอาจมีต้นทุนด้านประสิทธิภาพ
- มีเพียงคนขับเท่านั้นที่สามารถคำนวณเวลาที่ใช้ในตัวเองหรือบน Accelerator ไม่รวมเวลาที่ใช้ในรันไทม์ของ NNAPI และใน IPC
- คุณจะใช้ API เหล่านี้ได้เฉพาะกับ
ANeuralNetworksExecution
ที่ สร้างด้วยANeuralNetworksCompilation_createForDevices
กับnumDevices = 1
- ผู้ใช้ไม่จำเป็นต้องขับรถเพื่อรายงานข้อมูลเวลา
สร้างโปรไฟล์แอปพลิเคชันของคุณด้วย Android Systrace
NNAPI จะสร้างโดยอัตโนมัติสำหรับ Android 10 ตั้งแต่ Android 10 systrace ที่ คุณสามารถใช้โปรไฟล์ของแอปพลิเคชันได้
แหล่งที่มา NNAPI มาพร้อมกับยูทิลิตี parse_systrace
สำหรับการประมวลผล
เหตุการณ์ systrace ที่สร้างขึ้นโดยแอปพลิเคชันและสร้างมุมมองตารางที่แสดง
เวลาที่ใช้ในวงจรต่างๆ ของโมเดล (Instantiation,
การเตรียมความพร้อม การดำเนินการคอมไพล์ และการสิ้นสุด) และชั้นต่างๆ ของ
แอปพลิเคชัน เลเยอร์ที่แบ่งแอปพลิเคชันของคุณมีดังนี้
Application
: รหัสแอปพลิเคชันหลักRuntime
: รันไทม์ของ NNAPIIPC
: การสื่อสารระหว่างกระบวนการระหว่างรันไทม์ของ NNAPI และไดรเวอร์ รหัสDriver
: กระบวนการของไดรเวอร์ Accelerator
สร้างข้อมูลการวิเคราะห์โปรไฟล์
สมมติว่าคุณได้ดูแผนผังแหล่งที่มา AOSP ที่ $ANDROID_BUILD_TOP และ โดยใช้ตัวอย่างการจัดประเภทรูปภาพ TFLite เป็นแอปพลิเคชันเป้าหมาย คุณสามารถสร้างข้อมูลการทำโปรไฟล์ NNAPI ด้วยฟังก์ชัน ขั้นตอนต่อไปนี้
- เริ่ม Android systrace ด้วยคำสั่งต่อไปนี้
$ANDROID_BUILD_TOP/external/chromium-trace/systrace.py -o trace.html -a org.tensorflow.lite.examples.classification nnapi hal freq sched idle load binder_driver
พารามิเตอร์ -o trace.html
ระบุว่าการติดตามจะ
ซึ่งเขียนใน trace.html
เมื่อทำโปรไฟล์แอปพลิเคชันของตัวเอง คุณจำเป็นจะต้อง
แทนที่ org.tensorflow.lite.examples.classification
ด้วยชื่อกระบวนการ
ที่ระบุในไฟล์ Manifest ของแอป
การดำเนินการนี้จะทำให้คอนโซล Shell ของคุณไม่ว่าง โปรดอย่าเรียกใช้คำสั่งใน
เพราะเป็นการโต้ตอบที่รอให้ enter
สิ้นสุด
- หลังจากที่เริ่มใช้งานตัวรวบรวม Systrace แล้ว ให้เริ่มแอปและเรียกใช้ เปรียบเทียบ
ในกรณีของเรา คุณสามารถเริ่มแอปการจัดประเภทรูปภาพจาก Android Studio หรือจาก UI โทรศัพท์ทดสอบโดยตรงหากได้ติดตั้งแอปแล้ว หากต้องการสร้างข้อมูล NNAPI บางส่วน คุณต้องกำหนดค่าแอปให้ใช้ NNAPI ภายในวันที่ เลือก NNAPI เป็นอุปกรณ์เป้าหมายในกล่องโต้ตอบการกำหนดค่าแอป
เมื่อการทดสอบเสร็จสิ้น ให้สิ้นสุด Sytrace โดยกด
enter
เปิด เทอร์มินัลคอนโซลจะทำงานตั้งแต่ขั้นตอนที่ 1เรียกใช้ยูทิลิตี
systrace_parser
เพื่อสร้างสถิติสะสม:
$ANDROID_BUILD_TOP/frameworks/ml/nn/tools/systrace_parser/parse_systrace.py --total-times trace.html
โปรแกรมแยกวิเคราะห์จะยอมรับพารามิเตอร์ต่อไปนี้
- --total-times
: แสดงเวลาทั้งหมดที่ใช้ในเลเยอร์ รวมทั้งเวลา
ใช้เวลารอการดำเนินการสำหรับการเรียกไปยังเลเยอร์ที่สำคัญ
- --print-detail
: พิมพ์เหตุการณ์ทั้งหมดที่รวบรวมจาก systrace
- --per-execution
: พิมพ์เฉพาะการดำเนินการและเฟสย่อย
(เป็นจำนวนครั้งต่อการดำเนินการ) แทนที่จะเป็นสถิติสำหรับทุกระยะ
- --json
: สร้างเอาต์พุตในรูปแบบ JSON
ตัวอย่างเอาต์พุตจะแสดงที่ด้านล่าง
===========================================================================================================================================
NNAPI timing summary (total time, ms wall-clock) Execution
----------------------------------------------------
Initialization Preparation Compilation I/O Compute Results Ex. total Termination Total
-------------- ----------- ----------- ----------- ------------ ----------- ----------- ----------- ----------
Application n/a 19.06 1789.25 n/a n/a 6.70 21.37 n/a 1831.17*
Runtime - 18.60 1787.48 2.93 11.37 0.12 14.42 1.32 1821.81
IPC 1.77 - 1781.36 0.02 8.86 - 8.88 - 1792.01
Driver 1.04 - 1779.21 n/a n/a n/a 7.70 - 1787.95
Total 1.77* 19.06* 1789.25* 2.93* 11.74* 6.70* 21.37* 1.32* 1831.17*
===========================================================================================================================================
* This total ignores missing (n/a) values and thus is not necessarily consistent with the rest of the numbers
โปรแกรมแยกวิเคราะห์อาจล้มเหลวหากเหตุการณ์ที่รวบรวมไม่ได้แสดงถึง การติดตามแอปพลิเคชัน โดยเฉพาะอย่างยิ่ง อาจล้มเหลวหากมีการสร้างเหตุการณ์ systrace เพื่อทำเครื่องหมายจุดสิ้นสุดของส่วนมีอยู่ในการติดตามโดยไม่มีการเชื่อมโยง เหตุการณ์เริ่มต้นของส่วน กรณีนี้มักเกิดขึ้นเมื่อกิจกรรมบางอย่าง ระบบจะสร้างเซสชันการสร้างโปรไฟล์เมื่อคุณเริ่มต้นเครื่องมือรวบรวม systrace ในกรณีนี้ คุณจะต้องเรียกใช้การสร้างโปรไฟล์อีกครั้ง
เพิ่มสถิติสำหรับโค้ดแอปพลิเคชันของคุณไปยังเอาต์พุต systrace_parser
แอปพลิเคชัน parse_systrace จะขึ้นอยู่กับ Android systrace ในตัว คุณเพิ่มการติดตามสำหรับการทำงานที่เฉพาะเจาะจงในแอปได้โดยใช้ API ของ Systrace (สำหรับ Java สำหรับแอปพลิเคชันที่มาพร้อมเครื่อง ) พร้อมชื่อเหตุการณ์ที่กำหนดเอง
หากต้องการเชื่อมโยงเหตุการณ์ที่กำหนดเองกับขั้นตอนต่างๆ ของวงจรแอปพลิเคชัน แทรกสตริงใดสตริงหนึ่งต่อไปนี้ไว้ข้างหน้าชื่อเหตุการณ์
[NN_LA_PI]
: เหตุการณ์ระดับแอปพลิเคชันสำหรับการเริ่มต้น[NN_LA_PP]
: เหตุการณ์ระดับแอปพลิเคชันสำหรับการเตรียมพร้อม[NN_LA_PC]
: เหตุการณ์ระดับแอปพลิเคชันสำหรับการคอมไพล์[NN_LA_PE]
: เหตุการณ์ระดับแอปพลิเคชันสำหรับการดำเนินการ
ด้านล่างนี้เป็นตัวอย่างวิธีที่คุณสามารถปรับเปลี่ยนตัวอย่างการจัดประเภทรูปภาพ TFLite
โดยเพิ่มส่วน runInferenceModel
สำหรับระยะ Execution
และส่วน
Application
เลเยอร์ที่มีส่วนอื่นๆ อีก preprocessBitmap
ที่
จะไม่ได้รับการพิจารณาในการติดตาม NNAPI ส่วนrunInferenceModel
จะเป็น
ส่วนหนึ่งของเหตุการณ์ Systrace ที่ประมวลผลโดยโปรแกรมแยกวิเคราะห์ systrace ของ nnapi
Kotlin
/** Runs inference and returns the classification results. */ fun recognizeImage(bitmap: Bitmap): List{ // This section won’t appear in the NNAPI systrace analysis Trace.beginSection("preprocessBitmap") convertBitmapToByteBuffer(bitmap) Trace.endSection() // Run the inference call. // Add this method in to NNAPI systrace analysis. Trace.beginSection("[NN_LA_PE]runInferenceModel") long startTime = SystemClock.uptimeMillis() runInference() long endTime = SystemClock.uptimeMillis() Trace.endSection() ... return recognitions }
Java
/** Runs inference and returns the classification results. */ public ListrecognizeImage(final Bitmap bitmap) { // This section won’t appear in the NNAPI systrace analysis Trace.beginSection("preprocessBitmap"); convertBitmapToByteBuffer(bitmap); Trace.endSection(); // Run the inference call. // Add this method in to NNAPI systrace analysis. Trace.beginSection("[NN_LA_PE]runInferenceModel"); long startTime = SystemClock.uptimeMillis(); runInference(); long endTime = SystemClock.uptimeMillis(); Trace.endSection(); ... Trace.endSection(); return recognitions; }
คุณภาพของการบริการ
ใน Android 11 ขึ้นไป NNAPI จะทำให้คุณภาพของบริการ (QoS) ดีขึ้นโดย ช่วยให้แอปพลิเคชันระบุลำดับความสำคัญของโมเดลที่เกี่ยวข้อง ระยะเวลาสูงสุดที่คาดว่าจะใช้ในการเตรียมโมเดลที่กำหนด และระยะเวลาสูงสุด ของเวลาที่คาดว่าจะเสร็จสิ้นการคำนวณหนึ่งๆ Android 11 ยังเปิดตัว รหัสผลลัพธ์ของ NNAPI เพิ่มเติม ที่ช่วยให้แอปพลิเคชันเข้าใจความล้มเหลว เช่น การดำเนินการที่พลาดไป กำหนด
กำหนดลำดับความสำคัญของภาระงาน
หากต้องการตั้งค่าลำดับความสำคัญของภาระงาน NNAPI โปรดเรียกใช้
ANeuralNetworksCompilation_setPriority()
ก่อนที่จะโทรหา ANeuralNetworksCompilation_finish()
ตั้งกำหนดเวลา
แอปพลิเคชันสามารถกำหนดกำหนดเวลาสำหรับทั้งการคอมไพล์โมเดลและการอนุมานได้
- ในการตั้งค่าระยะหมดเวลาของการรวบรวม ให้เรียกใช้
ANeuralNetworksCompilation_setTimeout()
ก่อนที่จะโทรหาANeuralNetworksCompilation_finish()
- หากต้องการตั้งค่าระยะหมดเวลาของการอนุมาน โปรดเรียกใช้
ANeuralNetworksExecution_setTimeout()
ก่อนเริ่มการคอมไพล์
ข้อมูลเพิ่มเติมเกี่ยวกับตัวถูกดำเนินการ
ส่วนต่อไปนี้ครอบคลุมหัวข้อขั้นสูงเกี่ยวกับการใช้ตัวถูกดำเนินการ
Tensor ที่ปรับให้เล็กลง
Tensor ควอนไทล์คือวิธีกะทัดรัดที่ใช้แสดงอาร์เรย์ n มิติของ ค่าทศนิยม
NNAPI รองรับ Tensor แบบไม่สมมาตรแบบ 8 บิต สำหรับ Tensor เหล่านี้ ของแต่ละเซลล์จะแสดงด้วยจำนวนเต็ม 8 บิต เชื่อมโยงกับ tensor คือสเกลและค่าคะแนนเป็น 0 ส่วนนี้ใช้เพื่อแปลงค่า 8 บิต จำนวนเต็มในค่าทศนิยมที่แสดง
สูตรคือ
(cellValue - zeroPoint) * scale
โดยค่า ZeroPoint เป็นจำนวนเต็ม 32 บิต และค่าสเกล 32 บิตแบบลอย คะแนนเต็ม
เมื่อเปรียบเทียบกับ Tensor ของค่าจุดลอยตัว 32 บิต Tensor ที่ควอนไซส์ 8 บิต ข้อดี 2 ข้อ ได้แก่
- แอปพลิเคชันมีขนาดเล็กลง เนื่องจากน้ำหนักที่ฝึกแล้วใช้เวลา 1 ใน 4 ของขนาด Tensor 32 บิต
- การคำนวณมักดำเนินการได้เร็วขึ้น เนื่องจากจำนวนที่น้อยกว่า ของข้อมูลที่ต้องดึงจากหน่วยความจำและประสิทธิภาพของหน่วยประมวลผล เช่น DSP ในการคำนวณจำนวนเต็ม
แม้ว่าจะสามารถแปลงโมเดลจำนวนทศนิยมเป็นโมเดลที่เล็กลงได้ แสดงให้เห็นว่าการได้รับผลลัพธ์ที่ดีขึ้นจากการฝึกตัวแปร โมเดลโดยตรง โครงข่ายประสาทจะเรียนรู้ที่จะชดเชย รายละเอียดที่เพิ่มขึ้นของแต่ละค่า สำหรับแต่ละ Tensor ที่ปรับขนาดแล้ว ขนาด และ ระบบจะกำหนดค่า ZeroPoint ในระหว่างขั้นตอนการฝึก
ใน NNAPI คุณจะกำหนดประเภท Tensor ให้เล็กลงได้โดยตั้งค่าช่องประเภทของพารามิเตอร์
ANeuralNetworksOperandType
เพื่อ
ANEURALNETWORKS_TENSOR_QUANT8_ASYMM
คุณยังระบุสเกลและค่า ZeroPoint ของ tensor ในข้อมูลนั้นได้ด้วย
ใหม่
นอกจาก Tensor จำนวน 8 บิตแบบไม่สมมาตรแล้ว NNAPI ยังรองรับสิ่งต่อไปนี้ด้วย
ANEURALNETWORKS_TENSOR_QUANT8_SYMM_PER_CHANNEL
ซึ่งคุณสามารถใช้แสดงน้ำหนักกับCONV/DEPTHWISE_CONV/TRANSPOSED_CONV
การดำเนินการANEURALNETWORKS_TENSOR_QUANT16_ASYMM
ที่คุณสามารถใช้สำหรับสถานะภายในของQUANTIZED_16BIT_LSTM
ANEURALNETWORKS_TENSOR_QUANT8_SYMM
ซึ่งสามารถเป็นอินพุตสำหรับANEURALNETWORKS_DEQUANTIZE
ตัวถูกดำเนินการที่ไม่บังคับ
การดำเนินการบางอย่าง เช่น
ANEURALNETWORKS_LSH_PROJECTION
ใช้ตัวถูกดำเนินการที่ไม่บังคับ เพื่อระบุในโมเดลว่าตัวถูกดำเนินการที่ไม่บังคับคือ
ละเว้น ให้เรียกเมธอด
ANeuralNetworksModel_setOperandValue()
โดยส่ง NULL
สำหรับบัฟเฟอร์และ 0 สำหรับความยาว
ถ้าการตัดสินว่าตัวถูกดำเนินการมีหรือไม่แตกต่างกันในแต่ละรายการ
คุณจะระบุว่าตัวถูกละเว้นถูกละเว้นด้วยการใช้ฟังก์ชัน
ANeuralNetworksExecution_setInput()
หรือ
ANeuralNetworksExecution_setOutput()
ฟังก์ชัน โดยส่ง NULL
สำหรับบัฟเฟอร์และ 0 สำหรับความยาว
Tensor ของอันดับที่ไม่รู้จัก
Android 9 (API ระดับ 28) เปิดตัวตัวถูกดำเนินการโมเดลของมิติข้อมูลที่ไม่รู้จัก แต่ อันดับที่ทราบ (จำนวนมิติข้อมูล) เปิดตัว Android 10 (API ระดับ 29) 10 อันดับของอันดับที่ไม่รู้จักดังที่แสดงใน ANeuralNetworksOperandType
การเปรียบเทียบ NNAPI
การเปรียบเทียบ NNAPI มีให้บริการบน AOSP ในplatform/test/mlts/benchmark
(แอปเปรียบเทียบ) และ platform/test/mlts/models
(โมเดลและชุดข้อมูล)
เกณฑ์เปรียบเทียบนี้จะประเมินเวลาในการตอบสนองและความแม่นยำ แล้วเปรียบเทียบไดรเวอร์คนเดียวกัน ใช้ Tensorflow Lite ที่ทำงานบน CPU สำหรับรุ่นเดียวกันและ ชุดข้อมูล
ในการใช้การเปรียบเทียบ ให้ทำดังนี้
เชื่อมต่ออุปกรณ์ Android เป้าหมายกับคอมพิวเตอร์ เปิดหน้าต่างเทอร์มินัล และ ตรวจสอบว่าอุปกรณ์เข้าถึงได้ผ่าน adb
หากมีอุปกรณ์ Android มากกว่า 1 เครื่องเชื่อมต่ออยู่ ให้ส่งออกอุปกรณ์เป้าหมาย ตัวแปรสภาพแวดล้อม
ANDROID_SERIAL
ไปที่ไดเรกทอรีแหล่งที่มาระดับบนสุดของ Android
เรียกใช้คำสั่งต่อไปนี้
lunch aosp_arm-userdebug # Or aosp_arm64-userdebug if available ./test/mlts/benchmark/build_and_run_benchmark.sh
เมื่อสิ้นสุดการทำงานเปรียบเทียบ ผลลัพธ์จะแสดงเป็นหน้า HTML ผ่านไปยัง
xdg-open
บันทึกของ NNAPI
NNAPI จะสร้างข้อมูลการวินิจฉัยที่เป็นประโยชน์ในบันทึกของระบบ หากต้องการวิเคราะห์บันทึก ให้ใช้ logcat ยูทิลิตี
เปิดใช้การบันทึก NNAPI แบบละเอียดสำหรับเฟสหรือคอมโพเนนต์เฉพาะโดยการตั้งค่า
คุณสมบัติ debug.nn.vlog
(โดยใช้ adb shell
) ในรายการค่าต่อไปนี้
คั่นด้วยการเว้นวรรค เครื่องหมายโคลอน หรือคอมมา
model
: การสร้างแบบจำลองcompilation
: การสร้างแผนการดำเนินการโมเดลและคอมไพล์execution
: การดำเนินการโมเดลcpuexe
: การดำเนินการโดยใช้การใช้งาน CPU ของ NNAPImanager
: ข้อมูลที่เกี่ยวข้องกับส่วนขยาย NNAPI, อินเทอร์เฟซและความสามารถที่มีให้บริการall
หรือ1
: องค์ประกอบด้านบนทั้งหมด
ตัวอย่างเช่น หากต้องการเปิดการบันทึกแบบละเอียด ให้ใช้คำสั่ง
adb shell setprop debug.nn.vlog all
หากต้องการปิดใช้การบันทึกแบบละเอียด ให้ใช้คำสั่ง
adb shell setprop debug.nn.vlog '""'
เมื่อเปิดใช้ การบันทึกแบบละเอียดจะสร้างรายการบันทึกที่ระดับ INFO ด้วยแท็กที่ตั้งชื่อเฟสหรือคอมโพเนนต์
นอกเหนือจากข้อความที่มีการควบคุม debug.nn.vlog
แล้ว คอมโพเนนต์ NNAPI API ยัง
รายการบันทึกอื่นๆ ในหลายระดับ โดยแต่ละรายการจะใช้แท็กบันทึกเฉพาะ
หากต้องการดูรายการคอมโพเนนต์ ให้ค้นหาโครงสร้างแหล่งที่มาโดยใช้องค์ประกอบ นิพจน์ต่อไปนี้
grep -R 'define LOG_TAG' | awk -F '"' '{print $2}' | sort -u | egrep -v "Sample|FileTag|test"
ปัจจุบันนิพจน์นี้ส่งคืนแท็กต่อไปนี้
- สร้างภาพถ่ายอัจฉริยะ
- Callback
- CompilationBuilder
- CpuExecutor
- คำสั่งสร้างการดำเนินการ
- ExecutionBurstController
- เซิร์ฟเวอร์ ExecutionBurst
- แผนดำเนินการ
- ฟีโบนักชีไดรเวอร์
- กราฟ Dump
- IndexedShapeWrapper
- ผู้เฝ้าดู Ion
- ผู้จัดการ
- หน่วยความจำ
- ยูทิลิตีหน่วยความจำ
- โมเดลเมตา
- ข้อมูลอาร์กิวเมนต์ของโมเดล
- เครื่องมือสร้างโมเดล
- เครือข่ายระบบประสาท
- โอเปอเรเตอร์การแก้ไข
- การทำงาน
- ยูทิลิตีการดำเนินการ
- ข้อมูลแพ็กเกจ
- TokenHasher
- เครื่องมือจัดการประเภท
- ประโยชน์ใช้สอย
- ตรวจสอบความถูกต้องฮาล
- อินเทอร์เฟซที่มีเวอร์ชัน
หากต้องการควบคุมระดับของข้อความบันทึกที่แสดงโดย logcat
ให้ใช้
ตัวแปรสภาพแวดล้อม ANDROID_LOG_TAGS
หากต้องการแสดงข้อความบันทึก NNAPI ทั้งชุดและปิดใช้งานข้อความอื่นๆ ให้ตั้งค่า ANDROID_LOG_TAGS
เป็น
ดังต่อไปนี้
BurstBuilder:V Callbacks:V CompilationBuilder:V CpuExecutor:V ExecutionBuilder:V ExecutionBurstController:V ExecutionBurstServer:V ExecutionPlan:V FibonacciDriver:V GraphDump:V IndexedShapeWrapper:V IonWatcher:V Manager:V MemoryUtils:V Memory:V MetaModel:V ModelArgumentInfo:V ModelBuilder:V NeuralNetworks:V OperationResolver:V OperationsUtils:V Operations:V PackageInfo:V TokenHasher:V TypeManager:V Utils:V ValidateHal:V VersionedInterfaces:V *:S.
คุณตั้งค่า ANDROID_LOG_TAGS
ได้โดยใช้คำสั่งต่อไปนี้
export ANDROID_LOG_TAGS=$(grep -R 'define LOG_TAG' | awk -F '"' '{ print $2 ":V" }' | sort -u | egrep -v "Sample|FileTag|test" | xargs echo -n; echo ' *:S')
โปรดทราบว่านี่เป็นเพียงตัวกรองที่ใช้กับ logcat
เท่านั้น คุณยังต้อง
ตั้งค่าพร็อพเพอร์ตี้ debug.nn.vlog
เป็น all
เพื่อสร้างข้อมูลบันทึกแบบละเอียด