ส่วนขยายของผู้ให้บริการ 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
bit คือส่วนขยาย
คำนำหน้าและแอตทริบิวต์ต่ำ
Model::ExtensionTypeEncoding::LOW_BITS_TYPE
บิตแสดงประเภทหรือการดำเนินการ
ของส่วนขยาย
เมื่อจัดการการดำเนินการหรือประเภทออปเรอเรนต์ ไดรเวอร์ต้องตรวจสอบส่วนนำหน้าของส่วนขยาย หากคำนำหน้าส่วนขยายมีค่าที่ไม่ใช่ 0 ประเภทการดำเนินการหรือออปเรอเรนซ์จะเป็นประเภทส่วนขยาย ถ้าค่าเป็น 0
ประเภทของการดำเนินการหรือตัวถูกดำเนินการ
ไม่ใช่ประเภทส่วนขยาย
หากต้องการจับคู่คำนำหน้ากับชื่อส่วนขยาย ให้ค้นหาใน
model.extensionNameToPrefix
การแมปจากคำนำหน้าไปยังชื่อส่วนขยายเป็นการจับคู่แบบ 1:1 (การจับคู่แบบ 1-1) สำหรับโมเดลหนึ่งๆ ค่าคำนำหน้าที่แตกต่างกันอาจสอดคล้องกับชื่อชิ้นงานเดียวกันในรุ่นต่างๆ
ไดรเวอร์ต้องตรวจสอบการดำเนินการและประเภทข้อมูลของส่วนขยาย เนื่องจากรันไทม์ NNAPI ไม่สามารถตรวจสอบการดำเนินการและประเภทข้อมูลของส่วนขยายบางรายการได้
ออบเจ็กต์การดำเนินการของส่วนขยายอาจมีข้อมูลที่เชื่อมโยงใน operand.extraParams.extension
ซึ่งรันไทม์จะถือว่าเป็น Blob ข้อมูลดิบที่มีขนาดตามต้องการ
ประเภทข้อมูลและการดำเนินการ OEM
NNAPI มีการดำเนินการ OEM และประเภทข้อมูล OEM ที่จะอนุญาต
ผู้ผลิตรายใหม่ๆ เพื่อให้มีฟังก์ชันการทำงานที่ปรับแต่งเฉพาะสำหรับคนขับโดยเฉพาะ การดำเนินการและประเภทข้อมูลเหล่านี้ใช้โดยแอปพลิเคชันของ OEM เท่านั้น ความหมายของ OEM
การดำเนินการและข้อมูลประเภทต่างๆ เป็นแบบเฉพาะ OEM และเปลี่ยนแปลงได้ตลอดเวลา ระบบจะเข้ารหัสการดำเนินการและประเภทข้อมูลของ OEM โดยใช้ OperationType::OEM_OPERATION
,
OperandType::OEM
และ OperandType::TENSOR_OEM_BYTE