Tedarikçi uzantıları

Android 10'da kullanıma sunulan Neural Networks API (NNAPI) tedarikçi uzantıları, tedarikçi tarafından tanımlanan işlemlerin ve veri türlerinin koleksiyonlarıdır. NN HAL 1.2 veya daha yeni sürümlerin yüklü olduğu cihazlarda sürücüler, ilgili satıcı uzantılarını destekleyerek özel donanım hızlandırmalı işlemler sağlayabilir. Sağlayıcı 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ı kullanımı izin verilenler listesi

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

NNAPI sağlayıcı 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ında yeni bir giriş bulunur. Giriş, eğik çizgiyle (/) öneklenmiş 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 zorunlu kılınır. Bu kitaplık, NNAPI sürücüsü HAL arayüzünü doğrudan kullanan bir uygulamanın kasıtlı olarak engellemesini değil, yanlışlıkla kullanımını önler.

Tedarikçi uzantısı tanımı

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

Her uzantının, satıcını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 ad alanı olarak işlev görür. NNAPI, satıcı 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,
};

Uzantı işlemleri, uzantı olmayan işlenen türleri ve diğer uzantılardan gelen işlenen türleri de dahil olmak üzere herhangi bir işlenen türünü kullanabilir. Başka bir uzantıdan bir işlenen türü kullanırken sürücü, diğer uzantıyı desteklemelidir.

Uzantılar, uzantı işlenenlerine eşlik edecek özel yapılar da bildirebilir.

/**
 * 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ı uzantısı desteği sağlar. Bu bölümde C API'ye genel bir bakış sunulmaktadır.

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

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

Bir uzantı işleneniyle model oluşturmak için işlenen türünü elde etmek üzere ANeuralNetworksModel_getExtensionOperandType işlevini kullanın ve ANeuralNetworksModel_addOperand işlevini çağırı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ı işleneniyle ilişkilendirmek için ANeuralNetworksModel_setOperandExtensionData simgesini kullanın.

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

Uzantı işlemiyle model oluşturmak için ANeuralNetworksModel_getExtensionOperationType kullanarak işlem türünü alın ve ANeuralNetworksModel_addOperation işlevini ç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ş olmalı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 bitin yüksek Model::ExtensionTypeEncoding::HIGH_BITS_PREFIX bitleri, uzantı önekini, düşük Model::ExtensionTypeEncoding::LOW_BITS_TYPE bitleri ise uzantının türünü veya işlemini temsil eder.

Bir işlem veya işlenen türü işlenirken sürücü, uzantı önekini kontrol etmelidir. Uzantı öneki sıfır olmayan bir değere sahipse işlem veya işlenen türü bir uzantı türüdür. Değer 0 ise işlem veya işlenen türü bir uzantı türü değildir.

Ön eki bir uzantı adıyla eşlemek için model.extensionNameToPrefix adresinde arayın. Ön ekten uzantı adına yapılan eşleme, belirli bir model için bire bir eşleşmedir (bijeksiyon). Farklı önek 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ünün uzantı işlemlerini ve veri türlerini doğrulaması gerekir.

Uzantı işlenenleri, çalışma zamanının rastgele boyutta bir ham veri blobu olarak değerlendirdiği operand.extraParams.extension içinde ilişkili verilere sahip olabilir.

OEM işlemi ve veri türleri

NNAPI, cihaz üreticilerinin özel ve sürücüye özgü işlevler sağlamasına olanak tanıyan bir OEM işlemi ve OEM veri türlerine sahiptir. Bu işlem ve veri türleri yalnızca OEM uygulamaları tarafından kullanılır. OEM işlemi ve veri türlerinin semantiği OEM'e ö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.