Artımlı yürütmeler ve hızlı mesaj sıraları

Nöral Ağlar HAL 1.2, toplu yürütme kavramını kullanıma sunar. Seri çekim yürütme işlemleri, aynı hazırlanan modelin yürütülmesi sırasında gerçekleşen (ör. bir kamera görüntüsü karelerinde çalışan veya ardışık ses kullanabilirsiniz. Patlama nesnesi, bir dizi patlama yürütme işlemini kontrol etmek ve yürütmeler arasında kaynakları korumak için kullanılır. Böylece yürütme işlemlerinin daha düşük ek maliyete sahip olması sağlanır. Patlama nesneleri üç optimizasyonu etkinleştirir:

  1. Patlama nesnesi, bir yürütme dizisinden önce oluşturulur ve dizi sona erdiğinde serbest bırakılır. Bu nedenle, patlamanın ömrü, yüksek performansta kalması gerekene dair nesne ipuçları verir. durumu.
  2. Seri işlem 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 için eşlemeyi patlama nesnesinde önbelleğe alabilir. Önbelleğe alınmış tüm kaynaklar, patlama nesnesi yok edildiğinde veya NNAPI çalışma zamanı, patlama nesnesine kaynağın artık gerekli olmadığını bildirdiğinde serbest bırakılabilir.
  3. Patlama nesnesi, uygulama ile sürücü işlemleri arasında iletişim kurmak için hızlı mesaj sıralarını (FMQ'ler) kullanır. Bu FMQ HIDL'yi atlayıp verileri doğrudan ortak bellekte atomik dairesel bir FIFO yoluyla başka bir işlem. İlgili içeriği oluşturmak için kullanılan tüketici süreci bir öğeyi kuyruğa çıkaracağını ve veya FMQ'nun etkinliğini bekleyerek FIFO'daki element sayısını yoklama. işareti koyun. Bu etkinlik bayrağı hızlı kullanıcı alanı karşılıklı dışlama (futex) değeri.

FMQ, müşteri memnuniyeti açısından ömür boyu garanti sürecin süreçlerin tamamlanıp tamamlanmadığını belirlemek için yerleşik bir mekanizmaya sahip değildir. ve FMQ'nun diğer ucu beklendiği gibi çalışıyor. Sonuç olarak, FMQ için üretici sonlandırılırsa tüketici, hiçbir zaman gelmeyecek verileri beklemeye devam edebilir. Bu sorunun bir çözümü, sürücünün FMQ'leri, toplu yürütmenin ne zaman sona erdiğini algılamak için daha üst düzey toplu nesneyle ilişkilendirmesidir.

Art arda yürütme işlemleri aynı bağımsız değişkenlerle çalışır ve diğer yürütme yollarıyla aynı sonuçları döndürür. Bu nedenle, temel FMQ'ler NNAPI hizmet sürücülerine ve bu sürücülerden aynı verileri iletmelidir. Ancak FMQ'lar yalnızca veri türlerinden ibarettir. Karmaşık verilerin aktarımı, doğrudan FMQ'lerde iç içe yerleştirilmiş arabelleklerin (vektor türleri) serileştirilmesi ve seri dışı bırakılması ve bellek havuzu tutamaçlarını isteğe bağlı olarak aktarmak için HIDL geri çağırma nesnelerinin kullanılmasıyla gerçekleştirilir. FMQ'nin üretici tarafı, istek veya sonuç mesajlarını tüketiciye atomik olarak göndermelidir. Sıralı liste engelleniyorsa MessageQueue::writeBlocking, engellenmiyorsa MessageQueue::write kullanılmalıdır.

Seri çekim arayüzleri

Nöral Ağlar HAL'i için burst arayüzleri hardware/interfaces/neuralnetworks/1.2/ bölümünde bulunur ve aşağıda açıklanmıştır. NDK'daki seri arayüzler hakkında daha fazla bilgi için katmanı için frameworks/ml/nn/runtime/include/NeuralNetworks.h.

türler.hal

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

  • FmqRequestDatum: Hızlı mesaj kuyruğunda gönderilen bir yürütme Requestnesnesinin ve MeasureTiming değerinin serileştirilmiş temsilinin tek bir öğesi.
  • FmqResultDatum: Döndürülen değerlerin serileştirilmiş temsilinin tek bir öğesi (ErrorStatus, OutputShapes ve Timing) hızlı ileti kuyruğuna geri döndürülür.

IBurstContext.hal

IBurstContext.hal Nöral Ağlar hizmetinde bulunan HIDL arayüz nesnesini tanımlar.

  • IBurstContext: Bir artışın kaynaklarını yönetmek için kullanılan bağlam nesnesi.

IBurstCallback.hal

IBurstCallback.hal Nöral Ağlar tarafından oluşturulan bir geri çağırma için HIDL arayüz nesnesini tanımlar ve hidl_memory değerini almak için Nöral Ağlar hizmeti tarafından kullanılır nesne tanımlayıcılarını kullanı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şturma yöntemiyle genişletilmiştir.

  • configureExecutionBurst: Hazır bir projede birden fazla çıkarım yürütmek için kullanılan bir seri işlem nesnesini yapılandırır hızlı bir şekilde modeller.

Bir sürücüde seri yürütme işlemlerini destekleme

Bir HIDL NNAPI hizmetinde seri çekim nesneleri desteklemenin en basit yolu ::android::nn::ExecutionBurstServer::create seri çekim yardımcı programı bulundu ExecutionBurstServer.h ve libneuralnetworks_common ve libneuralnetworks_util olarak paketlenir olması gerekir. Bu fabrika işlevinin iki aşırı yüklemesi vardır:

  • Bir aşırı yükleme, IPreparedModel nesnesine işaretçi kabul eder. Bu yardımcı işlev, modeli yürütmek için IPreparedModel nesnesinde executeSynchronously yöntemini kullanır.
  • Bir aşırı yükleme, özelleştirilebilir IBurstExecutorWithCache nesnesi kabul ediyor Bu erişim, izin verilen kaynakları (ör. hidl_memory eşlemeleri) önbelleğe almak için birçok yürütmede kalıcı olur.

Her aşırı yükleme, kendi özel dinleyici iş parçacığını içeren ve yöneten bir IBurstContext nesnesi (patlama nesnesini temsil eder) döndürür. Bu iş parçacığı, requestChannel FMQ'den istek alır, çıkarım yapar ve sonuçları resultChannel FMQ üzerinden döndürür. Bu ileti dizisi ve tüm diğer IBurstContext nesnesinde bulunan kaynaklar otomatik olarak serbest bırakılır seri çekimin istemcisinin IBurstContext referansını kaybetmesi.

Alternatif olarak, IPreparedModel::configureExecutionBurst'a iletilen requestChannel ve resultChannel FMQ'leri üzerinden mesaj gönderip almayı anlayan kendi IBurstContext uygulamanızı oluşturabilirsiniz.

Seri çekim hizmet işlevleri ExecutionBurstServer.h içinde 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, Nöral Ağları örnek sürücüsü frameworks/ml/nn/driver/sample/SampleDriver.cpp.

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