वेंडर एक्सटेंशन

Neural Networks API (NNAPI) के वेंडर एक्सटेंशन, Android 10 में जोड़े गए हैं. ये वेंडर के तय किए गए ऑपरेशन और डेटा टाइप के कलेक्शन होते हैं. NN चलाने वाले डिवाइसों पर HAL 1.2 या उसके बाद के वर्शन में ड्राइवर, हार्डवेयर से तेज़ी लाने के लिए कस्टम ऑपरेशन दे सकते हैं के साथ काम करने वाले वेंडर एक्सटेंशन. वेंडर एक्सटेंशन, मौजूदा ऑपरेशन के व्यवहार में बदलाव नहीं करते.

वेंडर एक्सटेंशन, OEM के ऑपरेशन के लिए ज़्यादा स्ट्रक्चर्ड विकल्प देते हैं और डेटा टाइप जिन्हें Android 10 में बंद कर दिया गया था. ज़्यादा जानकारी के लिए, OEM ऑपरेशन और डेटा टाइप देखें.

एक्सटेंशन के इस्तेमाल की अनुमति वाली सूची

वेंडर एक्सटेंशन का इस्तेमाल सिर्फ़ साफ़ तौर पर बताए गए Android ऐप्लिकेशन और /product, /vendor, /odm, और /data पार्टिशन पर नेटिव बाइनरी. /system पार्टीशन में मौजूद ऐप्लिकेशन और नेटिव बाइनरी, वेंडर एक्सटेंशन का इस्तेमाल नहीं कर सकतीं.

/vendor/etc/nnapi_extensions_app_allowlist में, उन Android ऐप्लिकेशन और बाइनरी की सूची सेव की जाती है जिन्हें NNAPI वेंडर एक्सटेंशन इस्तेमाल करने की अनुमति मिली है. फ़ाइल की हर लाइन में एक नई एंट्री होती है. एंट्री, स्लैश (/) से शुरू होने वाला नेटिव बाइनरी पाथ हो सकता है. उदाहरण के लिए, /data/foo या Android ऐप्लिकेशन पैकेज का नाम, उदाहरण के लिए, com.foo.bar.

अनुमति वाली सूची को NNAPI रनटाइम की शेयर की गई लाइब्रेरी से लागू किया जाता है. यह लाइब्रेरी सेवा को अनजाने में इस्तेमाल किए जाने से बचाता है, लेकिन इसे जान-बूझकर गच्चा देने से नहीं ऐसा ऐप्लिकेशन जो सीधे NNAPI ड्राइवर HAL इंटरफ़ेस का इस्तेमाल करके बनाया गया हो.

वेंडर एक्सटेंशन की परिभाषा

वेंडर, एक्सटेंशन डेफ़िनिशन के साथ एक हेडर फ़ाइल बनाता है और उसे मैनेज करता है. एक्सटेंशन की परिभाषा का पूरा उदाहरण, 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, &params, 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. किसी मॉडल के लिए, प्रीफ़िक्स से एक्सटेंशन के नाम तक की मैपिंग, एक-से-एक संबंध (दो तरफ़ा संबंध) होती है. अलग-अलग प्रीफ़िक्स वैल्यू, अलग-अलग मॉडल में एक ही एक्सटेंशन के नाम से मेल खा सकती हैं.

ड्राइवर को एक्सटेंशन ऑपरेशन और डेटा टाइप की पुष्टि करनी होगी, क्योंकि NNAPI रनटाइम, एक्सटेंशन की खास कार्रवाइयों और डेटा टाइप की पुष्टि नहीं कर सकता.

एक्सटेंशन ऑपरेंड में, operand.extraParams.extension में डेटा जुड़ा हो सकता है. रनटाइम, इस डेटा को किसी भी साइज़ के रॉ डेटा ब्लॉब के तौर पर इस्तेमाल करता है.

OEM की कार्रवाई और डेटा टाइप

NNAPI में, OEM कार्रवाई होती है और OEM डेटा टाइप की अनुमति होती है डिवाइस निर्माता को कस्टम, ड्राइवर-विशिष्ट काम की क्षमता प्रदान करने के लिए. ये कार्रवाई और डेटा टाइप का इस्तेमाल सिर्फ़ OEM ऐप्लिकेशन करते हैं. OEM ऑपरेशन और डेटा टाइप के सेमेटिक्स, OEM के हिसाब से होते हैं और इन्हें कभी भी बदला जा सकता है. ओईएम ऑपरेशन और डेटा टाइप, OperationType::OEM_OPERATION का इस्तेमाल करके एन्कोड किए जाते हैं, OperandType::OEM और OperandType::TENSOR_OEM_BYTE.