הרחבות ספקים

תוספי ספקים של Neural Networks API (NNAPI), שהוצגו באנדרואיד 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, &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 . המיפוי מהקידומת לשם ההרחבה הוא התכתבות אחד לאחד (bijection) עבור דגם נתון. ערכי קידומת שונים עשויים להתאים לאותו שם תוסף בדגמים שונים.

מנהל ההתקן חייב לאמת פעולות הרחבה וסוגי נתונים מכיוון שזמן הריצה של NNAPI אינו יכול לאמת פעולות הרחבה וסוגי נתונים מסוימים.

לאופרנדים של הרחבה יכולים להיות נתונים משויכים ב- operand.extraParams.extension , שזמן הריצה מתייחס אליהם כאל גוש נתונים גולמי בגודל שרירותי.

תפעול OEM וסוגי נתונים

ל-NNAPI יש תפעול OEM וסוגי נתוני OEM כדי לאפשר ליצרני התקנים לספק פונקציונליות מותאמת אישית וספציפית לנהג. סוגי פעולות ונתונים אלה משמשים רק יישומי OEM. הסמנטיקה של תפעול OEM וסוגי נתונים הם ספציפיים ל-OEM ויכולה להשתנות בכל עת. פעולת ה-OEM וסוגי הנתונים מקודדים באמצעות OperationType::OEM_OPERATION , OperandType::OEM ו- OperandType::TENSOR_OEM_BYTE .