Seri yürütmeler ve hızlı mesaj kuyrukları

Sinir Ağları HAL 1.2, patlama yürütme kavramını tanıtıyor. Seri yürütmeler, bir kamera yakalama kareleri veya ardışık ses örnekleri üzerinde çalıştırılanlar gibi, aynı hazırlanmış modelin hızlı bir şekilde art arda gerçekleşen yürütme dizisidir. Bir çoğuşma nesnesi, bir dizi patlama yürütmesini kontrol etmek ve yürütmeler arasında kaynakları korumak, yürütmelerin daha düşük ek yüke sahip olmasını sağlamak için kullanılır. Burst nesneleri üç optimizasyona olanak sağlar:

  1. Bir patlama nesnesi, bir dizi yürütmeden önce oluşturulur ve dizi sona erdiğinde serbest bırakılır. Bu nedenle patlama nesnesinin ömrü, sürücüye yüksek performanslı durumda ne kadar süre kalması gerektiğine dair ipucu verir.
  2. Bir patlama nesnesi, yürütmeler arasında kaynakları koruyabilir. Örneğin, bir sürücü ilk yürütmede bir bellek nesnesini eşleyebilir ve sonraki yürütmelerde yeniden kullanmak üzere eşleştirmeyi patlama nesnesinde önbelleğe alabilir. Önbelleğe alınmış herhangi bir kaynak, patlama nesnesi yok edildiğinde veya NNAPI çalışma zamanı, kaynağın artık gerekli olmadığını patlama nesnesine bildirdiğinde serbest bırakılabilir.
  3. Bir patlama nesnesi, uygulama ve sürücü işlemleri arasında iletişim kurmak için hızlı mesaj kuyruklarını (FMQ'lar) kullanır. Bu, gecikmeyi azaltabilir çünkü FMQ, HIDL'yi atlar ve verileri, paylaşılan bellekteki atomik dairesel bir FIFO aracılığıyla doğrudan başka bir işleme aktarır. Tüketici süreci, FIFO'daki öğe sayısını yoklayarak veya üretici tarafından sinyal verilen FMQ olay bayrağını bekleyerek bir öğeyi kuyruktan çıkarmalı ve işlemeye başlamalıdır. Bu olay bayrağı hızlı bir kullanıcı alanı muteksidir (futex).

FMQ, süreçler arasında ömür boyu garanti sunmayan ve FMQ'nun diğer ucundaki sürecin beklendiği gibi çalışıp çalışmadığını belirlemek için yerleşik bir mekanizmaya sahip olmayan, düşük seviyeli bir veri yapısıdır. Sonuç olarak, FMQ'nun üreticisi ölürse tüketici hiçbir zaman gelmeyecek verileri beklemek zorunda kalabilir. Bu soruna bir çözüm, sürücünün, çoğuşma yürütmesinin ne zaman sona erdiğini algılamak için FMQ'ları daha yüksek düzeydeki çoğuşma nesnesiyle ilişkilendirmesidir.

Patlama yürütmeleri aynı bağımsız değişkenler üzerinde çalıştığından ve diğer yürütme yollarıyla aynı sonuçları döndürdüğünden, temeldeki FMQ'ların aynı verileri NNAPI hizmet sürücülerine ve NNAPI hizmet sürücülerinden iletmesi gerekir. Ancak FMQ'lar yalnızca düz eski veri türlerini aktarabilir. Karmaşık verilerin aktarılması, iç içe geçmiş arabelleklerin (vektör türleri) doğrudan FMQ'larda seri hale getirilmesi ve seri durumdan çıkarılmasıyla ve talep üzerine bellek havuzu tanıtıcılarını aktarmak için HIDL geri çağırma nesneleri kullanılarak gerçekleştirilir. FMQ'nun üretici tarafı, istek veya sonuç mesajlarını tüketiciye atomik olarak, kuyruk engelliyorsa, MessageQueue::writeBlocking kullanarak veya kuyruk engellenmiyorsa, MessageQueue::write kullanarak göndermelidir.

Seri arayüzler

Sinir Ağları HAL'sine yönelik patlama arayüzleri hardware/interfaces/neuralnetworks/1.2/ de bulunur ve aşağıda açıklanmaktadır. NDK katmanındaki patlama arayüzleri hakkında daha fazla bilgi için bkz. frameworks/ml/nn/runtime/include/NeuralNetworks.h .

türleri.hal

types.hal FMQ üzerinden gönderilen verinin türünü tanımlar.

  • FmqRequestDatum : Hızlı mesaj kuyruğu üzerinden gönderilen bir yürütme Request nesnesinin ve MeasureTiming değerinin serileştirilmiş temsilinin tek bir öğesi.
  • FmqResultDatum : Hızlı ileti kuyruğu aracılığıyla döndürülen bir yürütmeden ( ErrorStatus , OutputShapes ve Timing ) döndürülen değerlerin serileştirilmiş temsilinin tek bir öğesi.

IBurstContext.hal

IBurstContext.hal Sinir Ağları hizmetinde bulunan HIDL arabirim nesnesini tanımlar.

  • IBurstContext : Bir patlamanın kaynaklarını yönetmek için bağlam nesnesi.

IBurstCallback.hal

IBurstCallback.hal Sinir Ağları çalışma zamanı tarafından oluşturulan bir geri çağırma için HIDL arabirim nesnesini tanımlar ve Sinir Ağları hizmeti tarafından yuva tanımlayıcılarına karşılık gelen hidl_memory nesnelerini almak için kullanılır.

  • IBurstCallback : Bir hizmet tarafından bellek nesnelerini almak için kullanılan geri çağırma nesnesi.

IPreparedModel.hal

IPreparedModel.hal HAL 1.2'de hazırlanmış bir modelden IBurstContext nesnesi oluşturmaya yönelik bir yöntemle genişletildi.

  • configureExecutionBurst : Hazırlanan bir model üzerinde hızlı bir şekilde art arda birden fazla çıkarım yürütmek için kullanılan bir patlama nesnesini yapılandırır.

Bir sürücüde seri yürütmeleri destekleyin

Bir HIDL NNAPI hizmetinde patlama nesnelerini desteklemenin en basit yolu, ExecutionBurstServer.h bulunan ve libneuralnetworks_common ve libneuralnetworks_util statik kitaplıklarında paketlenmiş olan ::android::nn::ExecutionBurstServer::create işlevini kullanmaktır. Bu fabrika fonksiyonunun iki aşırı yükü vardır:

  • Bir aşırı yükleme, IPreparedModel nesnesine yönelik bir işaretçiyi kabul eder. Bu yardımcı program işlevi, modeli yürütmek için bir IPreparedModel nesnesindeki executeSynchronously yöntemini kullanır.
  • Bir aşırı yükleme, birden fazla yürütmede kalıcı olan kaynakları ( hidl_memory eşlemeleri gibi) önbelleğe almak için kullanılabilen özelleştirilebilir bir IBurstExecutorWithCache nesnesini kabul eder.

Her aşırı yükleme, kendi özel dinleyici iş parçacığını içeren ve yöneten bir IBurstContext nesnesini (burst nesnesini temsil eder) döndürür. Bu iş parçacığı, requestChannel FMQ'dan istekleri alır, çıkarımı gerçekleştirir ve ardından sonuçları resultChannel FMQ aracılığıyla döndürür. Bu iş parçacığı ve IBurstContext nesnesinde bulunan tüm diğer kaynaklar, patlamanın istemcisi IBurstContext olan referansını kaybettiğinde otomatik olarak serbest bırakılır.

Alternatif olarak, IPreparedModel::configureExecutionBurst öğesine iletilen requestChannel ve resultChannel FMQ'lar üzerinden nasıl mesaj gönderilip alınacağını anlayan kendi IBurstContext uygulamanızı oluşturabilirsiniz.

Burst yardımcı programı işlevleri ExecutionBurstServer.h dosyasında bulunur.

/**
 * Create automated context to manage FMQ-based executions.
 *
 * This function is intended to be used by a service to automatically:
 * 1) Receive data from a provided FMQ
 * 2) Execute a model with the given information
 * 3) Send the result to the created FMQ
 *
 * @param callback Callback used to retrieve memories corresponding to
 *     unrecognized slots.
 * @param requestChannel Input FMQ channel through which the client passes the
 *     request to the service.
 * @param resultChannel Output FMQ channel from which the client can retrieve
 *     the result of the execution.
 * @param executorWithCache Object which maintains a local cache of the
 *     memory pools and executes using the cached memory pools.
 * @result IBurstContext Handle to the burst context.
 */
static sp<ExecutionBurstServer> create(
        const sp<IBurstCallback>& callback, const FmqRequestDescriptor& requestChannel,
        const FmqResultDescriptor& resultChannel,
        std::shared_ptr<IBurstExecutorWithCache> executorWithCache);

/**
 * Create automated context to manage FMQ-based executions.
 *
 * This function is intended to be used by a service to automatically:
 * 1) Receive data from a provided FMQ
 * 2) Execute a model with the given information
 * 3) Send the result to the created FMQ
 *
 * @param callback Callback used to retrieve memories corresponding to
 *     unrecognized slots.
 * @param requestChannel Input FMQ channel through which the client passes the
 *     request to the service.
 * @param resultChannel Output FMQ channel from which the client can retrieve
 *     the result of the execution.
 * @param preparedModel PreparedModel that the burst object was created from.
 *     IPreparedModel::executeSynchronously will be used to perform the
 *     execution.
 * @result IBurstContext Handle to the burst context.
 */
  static sp<ExecutionBurstServer> create(const sp<IBurstCallback>& callback,
                                         const FmqRequestDescriptor& requestChannel,
                                         const FmqResultDescriptor& resultChannel,
                                         IPreparedModel* preparedModel);

Aşağıda frameworks/ml/nn/driver/sample/SampleDriver.cpp adresindeki Sinir Ağları örnek sürücüsünde bulunan bir patlama arayüzünün referans uygulaması yer almaktadır.

Return<void> SamplePreparedModel::configureExecutionBurst(
        const sp<V1_2::IBurstCallback>& callback,
        const MQDescriptorSync<V1_2::FmqRequestDatum>& requestChannel,
        const MQDescriptorSync<V1_2::FmqResultDatum>& resultChannel,
        configureExecutionBurst_cb cb) {
    NNTRACE_FULL(NNTRACE_LAYER_DRIVER, NNTRACE_PHASE_EXECUTION,
                 "SampleDriver::configureExecutionBurst");
    // Alternatively, the burst could be configured via:
    // const sp<V1_2::IBurstContext> burst =
    //         ExecutionBurstServer::create(callback, requestChannel,
    //                                      resultChannel, this);
    //
    // However, this alternative representation does not include a memory map
    // caching optimization, and adds overhead.
    const std::shared_ptr<BurstExecutorWithCache> executorWithCache =
            std::make_shared<BurstExecutorWithCache>(mModel, mDriver, mPoolInfos);
    const sp<V1_2::IBurstContext> burst = ExecutionBurstServer::create(
            callback, requestChannel, resultChannel, executorWithCache);
    if (burst == nullptr) {
        cb(ErrorStatus::GENERAL_FAILURE, {});
    } else {
        cb(ErrorStatus::NONE, burst);
    }
    return Void();
}