ส่วนขยายของผู้ขาย Neural Networks API (NNAPI) ที่เปิดตัวใน Android 10 คือชุดของการดำเนินการและประเภทข้อมูลที่ผู้ขายกำหนด บนอุปกรณ์ที่ใช้ NN HAL 1.2 หรือสูงกว่า ไดรเวอร์สามารถจัดเตรียมการดำเนินการเร่งด้วยฮาร์ดแวร์แบบกำหนดเองโดยสนับสนุนส่วนขยายของผู้จำหน่ายที่เกี่ยวข้อง ส่วนขยายของผู้จัดจำหน่ายไม่ปรับเปลี่ยนลักษณะการทำงานของการดำเนินงานที่มีอยู่
ส่วนขยายผู้ให้บริการเป็นทางเลือกที่มีโครงสร้างมากขึ้นสำหรับการดำเนินการของ OEM และประเภทข้อมูล ซึ่งเลิกใช้งานแล้วใน Android 10 สำหรับข้อมูลเพิ่มเติม โปรดดูที่ การดำเนินการของ OEM และประเภทข้อมูล
รายการอนุญาตการใช้งานส่วนขยาย
ส่วนขยายผู้จำหน่ายสามารถใช้ได้เฉพาะกับแอป Android และไบนารีดั้งเดิมที่ระบุอย่างชัดเจนบนพาร์ติชัน /product
, /vendor
, /odm
และ /data
แอปและไบนารีดั้งเดิมที่อยู่ในพาร์ติชัน /system
ไม่สามารถใช้ส่วนขยายของผู้จำหน่ายได้
รายการแอป Android และไบนารีที่ได้รับอนุญาตให้ใช้ส่วนขยายผู้ขาย NNAPI จะถูกจัดเก็บไว้ใน /vendor/etc/nnapi_extensions_app_allowlist
แต่ละบรรทัดของไฟล์มีรายการใหม่ รายการอาจเป็นเส้นทางไบนารีดั้งเดิมที่ขึ้นต้นด้วยเครื่องหมายทับ (/) เช่น /data/foo
หรือชื่อของแพ็คเกจแอป Android เช่น com.foo.bar
รายการที่อนุญาตบังคับใช้จากไลบรารีที่ใช้ร่วมกันของรันไทม์ NNAPI ไลบรารีนี้ป้องกันการใช้งานโดยไม่ได้ตั้งใจ แต่ไม่ป้องกันการจงใจหลบเลี่ยงโดยแอปโดยตรงโดยใช้อินเทอร์เฟซ HAL ของไดรเวอร์ NNAPI
คำนิยามส่วนขยายของผู้จัดจำหน่าย
ผู้จัดจำหน่ายสร้างและดูแลรักษาไฟล์ส่วนหัวที่มีข้อกำหนดส่วนขยาย ตัวอย่างที่สมบูรณ์ของคำจำกัดความส่วนขยายสามารถพบได้ใน example/fibonacci/FibonacciExtension.h
แต่ละส่วนขยายจะต้องมีชื่อเฉพาะที่ขึ้นต้นด้วยชื่อโดเมนย้อนกลับของผู้จำหน่าย
const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";
ชื่อทำหน้าที่เป็นเนมสเปซสำหรับการดำเนินการและชนิดข้อมูล NNAPI ใช้ชื่อนี้เพื่อแยกความแตกต่างระหว่างส่วนขยายของผู้จำหน่าย
การดำเนินการและประเภทข้อมูลได้รับการประกาศในลักษณะที่คล้ายคลึงกับการดำเนินการและประเภทข้อมูลใน runtime/include/NeuralNetworks.h
enum {
/**
* A custom scalar type.
*/
EXAMPLE_SCALAR = 0,
/**
* A custom tensor type.
*
* Attached to this tensor is {@link ExampleTensorParams}.
*/
EXAMPLE_TENSOR = 1,
};
enum {
/**
* Computes example function.
*
* Inputs:
* * 0: A scalar of {@link EXAMPLE_SCALAR}.
*
* Outputs:
* * 0: A tensor of {@link EXAMPLE_TENSOR}.
*/
EXAMPLE_FUNCTION = 0,
};
การดำเนินการส่วนขยายสามารถใช้ตัวถูกดำเนินการประเภทใดก็ได้ รวมถึงประเภทตัวถูกดำเนินการที่ไม่มีส่วนขยายและประเภทตัวถูกดำเนินการจากส่วนขยายอื่น เมื่อใช้ประเภทตัวถูกดำเนินการจากส่วนขยายอื่น ไดรเวอร์จะต้องรองรับส่วนขยายอื่น
ส่วนขยายยังสามารถประกาศโครงสร้างแบบกำหนดเองเพื่อประกอบกับตัวถูกดำเนินการส่วนขยาย
/**
* Quantization parameters for {@link EXAMPLE_TENSOR}.
*/
typedef struct ExampleTensorParams {
double scale;
int64_t zeroPoint;
} ExampleTensorParams;
ใช้ส่วนขยายในไคลเอนต์ NNAPI
ไฟล์ runtime/include/NeuralNetworksExtensions.h
(C API) ให้การสนับสนุนส่วนขยายรันไทม์ ส่วนนี้จะแสดงภาพรวมของ C API
หากต้องการตรวจสอบว่าอุปกรณ์รองรับส่วนขยายหรือไม่ ให้ใช้ ANeuralNetworksDevice_getExtensionSupport
bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
&isExtensionSupported),
ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
// The device supports the extension.
...
}
หากต้องการสร้างโมเดลที่มีตัวถูกดำเนินการส่วนขยาย ให้ใช้ ANeuralNetworksModel_getExtensionOperandType
เพื่อรับประเภทตัวถูกดำเนินการและเรียก ANeuralNetworksModel_addOperand
int32_t type;
CHECK_EQ(ANeuralNetworksModel_getExtensionOperandType(model, EXAMPLE_EXTENSION_NAME, EXAMPLE_TENSOR, &type),
ANEURALNETWORKS_NO_ERROR);
ANeuralNetworksOperandType operandType{
.type = type,
.dimensionCount = dimensionCount,
.dimensions = dimensions,
};
CHECK_EQ(ANeuralNetworksModel_addOperand(model, &operandType), ANEURALNETWORKS_NO_ERROR);
ทางเลือก ให้ใช้ ANeuralNetworksModel_setOperandExtensionData
เพื่อเชื่อมโยงข้อมูลเพิ่มเติมกับตัวถูกดำเนินการส่วนขยาย
ExampleTensorParams params{
.scale = 0.5,
.zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, ¶ms, sizeof(params)),
ANEURALNETWORKS_NO_ERROR);
หากต้องการสร้างโมเดลที่มีการดำเนินการส่วนขยาย ให้ใช้ ANeuralNetworksModel_getExtensionOperationType
เพื่อรับประเภทการดำเนินการและเรียก ANeuralNetworksModel_addOperation
ANeuralNetworksOperationType type;
CHECK_EQ(ANeuralNetworksModel_getExtensionOperationType(model, EXAMPLE_EXTENSION_NAME, EXAMPLE_FUNCTION,
&type),
ANEURALNETWORKS_NO_ERROR);
CHECK_EQ(ANeuralNetworksModel_addOperation(model, type, inputCount, inputs, outputCount, outputs),
ANEURALNETWORKS_NO_ERROR);
เพิ่มการรองรับส่วนขยายให้กับไดรเวอร์ NNAPI
ไดรเวอร์รายงานส่วนขยายที่รองรับผ่านวิธี IDevice::getSupportedExtensions
รายการที่ส่งคืนจะต้องมีรายการที่อธิบายส่วนขยายที่รองรับแต่ละรายการ
Extension {
.name = EXAMPLE_EXTENSION_NAME,
.operandTypes = {
{
.type = EXAMPLE_SCALAR,
.isTensor = false,
.byteSize = 8,
},
{
.type = EXAMPLE_TENSOR,
.isTensor = true,
.byteSize = 8,
},
},
}
จาก 32 บิตที่ใช้ในการระบุประเภทและการดำเนินการ บิต Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX
สูงเป็น คำนำหน้าส่วน ขยาย และบิต Model::ExtensionTypeEncoding::LOW_BITS_TYPE
ต่ำแสดงถึงประเภทหรือการทำงานของส่วนขยาย
เมื่อจัดการการทำงานหรือประเภทตัวถูกดำเนินการ คนขับจะต้องตรวจสอบคำนำหน้าส่วนขยาย หากคำนำหน้าส่วนขยายมีค่าที่ไม่ใช่ศูนย์ การดำเนินการหรือประเภทตัวถูกดำเนินการจะเป็นประเภทส่วนขยาย หากค่าเป็น 0
แสดงว่าการดำเนินการหรือประเภทตัวถูกดำเนินการไม่ใช่ประเภทส่วนขยาย
หากต้องการแมปคำนำหน้ากับชื่อส่วนขยาย ให้ค้นหาใน model.extensionNameToPrefix
การแมปจากคำนำหน้าไปยังชื่อส่วนขยายเป็นการโต้ตอบแบบหนึ่งต่อหนึ่ง (bijection) สำหรับโมเดลที่กำหนด ค่าคำนำหน้าที่แตกต่างกันอาจสอดคล้องกับชื่อส่วนขยายเดียวกันในรุ่นที่แตกต่างกัน
ไดรเวอร์จะต้องตรวจสอบการดำเนินการของส่วนขยายและประเภทข้อมูล เนื่องจากรันไทม์ NNAPI ไม่สามารถตรวจสอบการดำเนินการของส่วนขยายและประเภทข้อมูลเฉพาะได้
ตัวถูกดำเนินการส่วนขยายสามารถมีข้อมูลที่เกี่ยวข้องใน operand.extraParams.extension
ซึ่งรันไทม์ถือเป็นหยดข้อมูลดิบในขนาดที่กำหนดเอง
การดำเนินงาน OEM และประเภทข้อมูล
NNAPI มีการดำเนินการของ OEM และประเภทข้อมูล OEM เพื่อให้ผู้ผลิตอุปกรณ์สามารถมอบฟังก์ชันการทำงานเฉพาะไดรเวอร์แบบกำหนดเองได้ ประเภทการดำเนินการและข้อมูลเหล่านี้ถูกใช้โดยแอปพลิเคชัน OEM เท่านั้น ความหมายของการดำเนินการของ OEM และชนิดข้อมูลเป็นแบบเฉพาะของ OEM และสามารถเปลี่ยนแปลงได้ตลอดเวลา ประเภทการดำเนินการและข้อมูลของ OEM ได้รับการเข้ารหัสโดยใช้ OperationType::OEM_OPERATION
, OperandType::OEM
และ OperandType::TENSOR_OEM_BYTE