Tedarikçi uzantıları

Android 10'da kullanıma sunulan Neural Networks API (NNAPI) tedarikçi firma uzantıları, tedarikçi firma tarafından tanımlanan işlem ve veri türlerinin koleksiyonlarıdır. NN HAL 1.2 veya daha yeni sürümleri çalıştıran cihazlarda sürücüler, ilgili tedarikçi uzantılarını destekleyerek özel donanım hızlandırmalı işlemler sağlayabilir. Tedarikçi firma uzantıları, mevcut işlemlerin davranışını değiştirmez.

Tedarikçi uzantıları, Android 10'da desteği sonlandırılan OEM işlemi ve veri türlerine daha yapılandırılmış bir alternatif sunar. Daha fazla bilgi için OEM işlemi ve veri türleri başlıklı makaleyi inceleyin.

Uzantıların kullanımı izin verilenler listesi

Tedarikçi uzantıları yalnızca açıkça belirtilen Android uygulamaları ve /product, /vendor, /odm ve /data bölümlerindeki yerel ikili dosyalar tarafından kullanılabilir. /system bölümünde bulunan uygulamalar ve doğal ikili dosyalar tedarikçi uzantılarını kullanamaz.

NNAPI tedarikçi uzantılarını kullanmasına izin verilen Android uygulamalarının ve ikili dosyalarının listesi /vendor/etc/nnapi_extensions_app_allowlist içinde saklanır. Dosyanın her satırı yeni bir giriş içerir. Giriş, önüne eğik çizgi (/) eklenen yerel bir ikili yol (ör. /data/foo) veya bir Android uygulama paketinin adı (ör. com.foo.bar) olabilir.

İzin verilenler listesi, NNAPI çalışma zamanı paylaşılan kitaplığından uygulanır. Bu kitaplık, yanlışlıkla kullanıma karşı koruma sağlar ancak doğrudan NNAPI sürücü HAL arayüzünü kullanan bir uygulamanın kasıtlı olarak bu korumayı atlatmasına karşı koruma sağlamaz.

Tedarikçi firma uzantısı tanımı

Tedarikçi, uzantı tanımını içeren bir başlık dosyası oluşturur ve bu dosyayı yönetir. Uzatma tanımının tam örneğini example/fibonacci/FibonacciExtension.h adresinde bulabilirsiniz.

Her uzantının, tedarikçi firmanın ters alan adıyla başlayan benzersiz bir adı olmalıdır.

const char EXAMPLE_EXTENSION_NAME[] = "com.example.my_extension";

Ad, işlemler ve veri türleri için bir ad alanı görevi görür. NNAPI, tedarikçi uzantılarını ayırt etmek için bu adı kullanır.

İşlemler ve veri türleri, runtime/include/NeuralNetworks.h'dakilere benzer şekilde tanımlanır.

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,
};

Uzatma işlemi, uzantı olmayan operatör türleri ve diğer uzantılardaki operatör türleri dahil olmak üzere herhangi bir operatör türünü kullanabilir. Başka bir uzantıdaki bir operatör türü kullanıldığında sürücü, diğer uzantıyı desteklemelidir.

Uzantıların, uzantı operatörlerine eşlik edecek özel yapılar da tanımlayabileceğini unutmayın.

/**
 * Quantization parameters for {@link EXAMPLE_TENSOR}.
 */
typedef struct ExampleTensorParams {
    double scale;
    int64_t zeroPoint;
} ExampleTensorParams;

NNAPI istemcilerinde uzantıları kullanma

runtime/include/NeuralNetworksExtensions.h (C API) dosyası, çalışma zamanında uzantı desteği sağlar. Bu bölümde C API'ye genel bakış sunulmaktadır.

Bir cihazın uzantıyı destekleyip desteklemediğini kontrol etmek için ANeuralNetworksDevice_getExtensionSupport simgesini kullanın.

bool isExtensionSupported;
CHECK_EQ(ANeuralNetworksDevice_getExtensionSupport(device, EXAMPLE_EXTENSION_NAME,
                                                   &isExtensionSupported),
         ANEURALNETWORKS_NO_ERROR);
if (isExtensionSupported) {
    // The device supports the extension.
    ...
}

Uzatma operanı içeren bir model oluşturmak için operan türünü elde etmek ve ANeuralNetworksModel_addOperand'i çağırmak üzere ANeuralNetworksModel_getExtensionOperandType kullanın.

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);

İsteğe bağlı olarak, ek verileri bir uzantı operatörüyle ilişkilendirmek için ANeuralNetworksModel_setOperandExtensionData kullanın.

ExampleTensorParams params{
        .scale = 0.5,
        .zeroPoint = 128,
};
CHECK_EQ(ANeuralNetworksModel_setOperandExtensionData(model, operandIndex, &params, sizeof(params)),
         ANEURALNETWORKS_NO_ERROR);

Uzatma işlemi içeren bir model oluşturmak için ANeuralNetworksModel_getExtensionOperationType kullanarak işlem türünü alın ve ANeuralNetworksModel_addOperation'i çağırın.

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 sürücüsüne uzantı desteği ekleme

Sürücüler, desteklenen uzantıları IDevice::getSupportedExtensions yöntemiyle bildirir. Döndürülen listede, desteklenen her uzantıyı açıklayan bir giriş bulunmalıdır.

Extension {
    .name = EXAMPLE_EXTENSION_NAME,
    .operandTypes = {
        {
            .type = EXAMPLE_SCALAR,
            .isTensor = false,
            .byteSize = 8,
        },
        {
            .type = EXAMPLE_TENSOR,
            .isTensor = true,
            .byteSize = 8,
        },
    },
}

Türleri ve işlemleri tanımlamak için kullanılan 32 bitten yüksek Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX bitleri uzantı ön ekiyle ilişkilidir. Düşük Model::ExtensionTypeEncoding::LOW_BITS_TYPE bitleri ise uzantının türünü veya işlemini temsil eder.

Sürücü, bir işlem veya operant türünü işlerken uzantı ön ekini kontrol etmelidir. Uzatma ön ekinde sıfır olmayan bir değer varsa işlem veya operant türü bir uzantı türüdür. Değer 0 ise işlem veya operant türü bir uzantı türü değildir.

Ön eki bir uzantı adıyla eşlemek için model.extensionNameToPrefix'da arayın. Ön ek ile uzantı adı arasındaki eşleme, belirli bir model için bire bir ilişkidir (bijection). Farklı ön ek değerleri, farklı modellerde aynı uzantı adına karşılık gelebilir.

NNAPI çalışma zamanı belirli uzantı işlemlerini ve veri türlerini doğrulayamadığından sürücü, uzantı işlemlerini ve veri türlerini doğrulamalıdır.

Uzantı operatörleri, çalışma zamanında rastgele boyuttaki ham veri kümesi olarak işlenen operand.extraParams.extension içinde ilişkili verilere sahip olabilir.

OEM işlemi ve veri türleri

NNAPI, cihaz üreticilerinin sürücüye özel özel işlevler sunmasına olanak tanıyan bir OEM işlemine ve OEM veri türlerine sahiptir. Bu işlem ve veri türleri yalnızca OEM uygulamaları tarafından kullanılır. OEM işleminin ve veri türlerinin semantikleri OEM'ye özeldir ve herhangi bir zamanda değişebilir. OEM işlemi ve veri türleri OperationType::OEM_OPERATION, OperandType::OEM ve OperandType::TENSOR_OEM_BYTE kullanılarak kodlanır.