ফাঁসি কার্যকর এবং দ্রুত বার্তা সারি

নিউরাল নেটওয়ার্ক এইচএএল 1.2 বার্স্ট এক্সিকিউশনের ধারণা প্রবর্তন করে। বার্স্ট এক্সিকিউশন হল একই প্রস্তুত মডেলের মৃত্যুদন্ডের একটি ক্রম যা দ্রুত পর্যায়ক্রমে ঘটে, যেমন ক্যামেরা ক্যাপচারের ফ্রেমে কাজ করা বা ধারাবাহিক অডিও নমুনা। একটি বিস্ফোরিত অবজেক্ট ব্যবহার করা হয় বিস্ফোরিত মৃত্যুদণ্ডের একটি সেট নিয়ন্ত্রণ করতে এবং মৃত্যুদণ্ডের মধ্যে সংস্থানগুলি সংরক্ষণ করতে, মৃত্যুদন্ডকে নিম্ন ওভারহেড করতে সক্ষম করে। বিস্ফোরিত বস্তু তিনটি অপ্টিমাইজেশান সক্ষম করে:

  1. একটি বিস্ফোরিত বস্তু কার্যকর করার একটি ক্রম আগে তৈরি করা হয়, এবং ক্রম শেষ হয়ে গেলে মুক্ত করা হয়। এই কারণে, বিস্ফোরিত বস্তুর জীবনকাল একজন ড্রাইভারকে নির্দেশ করে যে কতক্ষণ এটি একটি উচ্চ-কর্মক্ষমতা অবস্থায় থাকা উচিত।
  2. একটি বিস্ফোরিত বস্তু মৃত্যুদন্ডের মধ্যে সম্পদ সংরক্ষণ করতে পারে। উদাহরণস্বরূপ, একজন ড্রাইভার প্রথম এক্সিকিউশনে একটি মেমরি অবজেক্ট ম্যাপ করতে পারে এবং পরবর্তী এক্সিকিউশনে পুনঃব্যবহারের জন্য বার্স্ট অবজেক্টে ম্যাপিং ক্যাশে করতে পারে। যখন বার্স্ট অবজেক্টটি ধ্বংস হয়ে যায় বা যখন NNAPI রানটাইম বার্স্ট অবজেক্টকে জানিয়ে দেয় যে রিসোর্সটির আর প্রয়োজন নেই তখন যেকোন ক্যাশ করা রিসোর্স রিলিজ করা যেতে পারে।
  3. একটি বিস্ফোরিত বস্তু অ্যাপ এবং ড্রাইভার প্রক্রিয়ার মধ্যে যোগাযোগ করতে দ্রুত বার্তা সারি (FMQs) ব্যবহার করে। এটি লেটেন্সি কমাতে পারে কারণ FMQ HIDL বাইপাস করে এবং শেয়ার্ড মেমরিতে একটি পারমাণবিক বৃত্তাকার FIFO এর মাধ্যমে সরাসরি অন্য প্রক্রিয়ায় ডেটা পাস করে। ভোক্তা প্রক্রিয়া একটি আইটেমকে সারিবদ্ধ করতে জানে এবং হয় FIFO-তে উপাদানের সংখ্যা পোল করে বা FMQ-এর ইভেন্ট পতাকার উপর অপেক্ষা করে প্রক্রিয়াকরণ শুরু করতে জানে, যা প্রযোজকের দ্বারা সংকেত হয়। এই ইভেন্ট পতাকা একটি দ্রুত ইউজারস্পেস মিউটেক্স (ফুটেক্স)।

একটি এফএমকিউ হল একটি নিম্ন-স্তরের ডেটা স্ট্রাকচার যা সমস্ত প্রক্রিয়া জুড়ে কোনও আজীবন গ্যারান্টি দেয় না এবং এফএমকিউর অন্য প্রান্তে প্রসেসটি প্রত্যাশিতভাবে চলছে কিনা তা নির্ধারণ করার জন্য কোনও অন্তর্নির্মিত ব্যবস্থা নেই। ফলস্বরূপ, যদি FMQ-এর প্রযোজক মারা যায়, তাহলে ভোক্তা এমন ডেটার জন্য অপেক্ষা করতে পারে যা কখনই আসে না। এই সমস্যার একটি সমাধান হল চালকের জন্য FMQ-গুলিকে উচ্চ-স্তরের বার্স্ট অবজেক্টের সাথে সংযুক্ত করা যাতে বিস্ফোরণটি শেষ হয়ে যায়।

যেহেতু বার্স্ট এক্সিকিউশনগুলি একই আর্গুমেন্টে কাজ করে এবং অন্যান্য এক্সিকিউশন পাথের মতো একই ফলাফল দেয়, অন্তর্নিহিত FMQ গুলিকে অবশ্যই NNAPI পরিষেবা ড্রাইভারের কাছে এবং থেকে একই ডেটা পাস করতে হবে। যাইহোক, FMQ শুধুমাত্র প্লেইন-পুরানো-ডেটা টাইপ স্থানান্তর করতে পারে। জটিল তথ্য স্থানান্তর সরাসরি FMQs-এ নেস্টেড বাফার (ভেক্টরের ধরন) সিরিয়ালাইজিং এবং ডিসিরিয়ালাইজ করে এবং চাহিদা অনুযায়ী মেমরি পুল হ্যান্ডলগুলি স্থানান্তর করতে HIDL কলব্যাক অবজেক্ট ব্যবহার করে সম্পন্ন করা হয়। FMQ-এর প্রযোজক পক্ষকে অবশ্যই গ্রাহকের কাছে অনুরোধ বা ফলাফলের বার্তা পাঠাতে হবে পরমাণুভাবে MessageQueue::writeBlocking যদি সারি ব্লক করা হয়, অথবা MessageQueue::write ব্যবহার করে যদি সারিটি ব্লক না হয়।

বিস্ফোরিত ইন্টারফেস

নিউরাল নেটওয়ার্ক এইচএএল-এর জন্য বিস্ফোরিত ইন্টারফেসগুলি hardware/interfaces/neuralnetworks/1.2/ -এ পাওয়া যায় এবং নীচে বর্ণনা করা হয়েছে। NDK স্তরে বার্স্ট ইন্টারফেস সম্পর্কে আরও তথ্যের জন্য, দেখুন frameworks/ml/nn/runtime/include/NeuralNetworks.h

type.hal

types.hal FMQ জুড়ে পাঠানো ডেটার ধরনকে সংজ্ঞায়িত করে।

  • FmqRequestDatum : একটি এক্সিকিউশন Request অবজেক্টের ক্রমিক উপস্থাপনা এবং একটি MeasureTiming মানের একটি একক উপাদান, যা দ্রুত বার্তা সারিতে পাঠানো হয়।
  • FmqResultDatum : একটি এক্সিকিউশন ( ErrorStatus , OutputShapes , and Timing ) থেকে ফিরে আসা মানগুলির ক্রমিক উপস্থাপনের একটি একক উপাদান, যা দ্রুত বার্তা সারির মাধ্যমে ফিরে আসে।

IBurstContext.hal

IBurstContext.hal HIDL ইন্টারফেস অবজেক্টকে সংজ্ঞায়িত করে যা নিউরাল নেটওয়ার্ক সার্ভিসে থাকে।

  • IBurstContext : একটি বিস্ফোরণের সংস্থানগুলি পরিচালনা করার জন্য প্রসঙ্গ অবজেক্ট।

IBurstCallback.hal

IBurstCallback.hal নিউরাল নেটওয়ার্ক রানটাইম দ্বারা তৈরি একটি কলব্যাকের জন্য HIDL ইন্টারফেস অবজেক্টকে সংজ্ঞায়িত করে এবং স্লট শনাক্তকারীর সাথে সম্পর্কিত hidl_memory বস্তুগুলি পুনরুদ্ধার করতে নিউরাল নেটওয়ার্ক পরিষেবা দ্বারা ব্যবহৃত হয়।

  • IBurstCallback : মেমরি বস্তু পুনরুদ্ধার করতে একটি পরিষেবা দ্বারা ব্যবহৃত কলব্যাক অবজেক্ট।

#preparedModel.hal

IPreparedModel.hal একটি প্রস্তুত মডেল থেকে একটি IBurstContext অবজেক্ট তৈরি করার পদ্ধতি সহ HAL 1.2-এ প্রসারিত হয়েছে।

  • configureExecutionBurst : একটি প্রস্তুতকৃত মডেলে দ্রুত ধারাবাহিকভাবে একাধিক অনুমান নির্বাহ করতে ব্যবহৃত একটি বার্স্ট অবজেক্ট কনফিগার করে।

একটি ড্রাইভার মধ্যে সমর্থন বিস্ফোরণ মৃত্যুদন্ড

HIDL NNAPI পরিষেবাতে বার্স্ট অবজেক্টগুলিকে সমর্থন করার সবচেয়ে সহজ উপায় হল বার্স্ট ইউটিলিটি ফাংশন ::android::nn::ExecutionBurstServer::create ব্যবহার করা, যা ExecutionBurstServer.h এ পাওয়া যায় এবং libneuralnetworks_common এবং libneuralnetworks_util এ প্যাকেজ করা হয়। এই কারখানা ফাংশন দুটি ওভারলোড আছে:

  • একটি ওভারলোড একটি IPreparedModel অবজেক্টে একটি পয়েন্টার গ্রহণ করে। এই ইউটিলিটি ফাংশনটি মডেলটি চালানোর জন্য একটি IPreparedModel অবজেক্টে executeSynchronously পদ্ধতি ব্যবহার করে।
  • একটি ওভারলোড একটি কাস্টমাইজযোগ্য IBurstExecutorWithCache অবজেক্ট গ্রহণ করে, যেটি সম্পদ ক্যাশে করতে ব্যবহার করা যেতে পারে (যেমন hidl_memory ম্যাপিং) যা একাধিক মৃত্যুদন্ড জুড়ে থাকে।

প্রতিটি ওভারলোড একটি IBurstContext অবজেক্ট (যা বার্স্ট অবজেক্টের প্রতিনিধিত্ব করে) ফেরত দেয় যা তার নিজস্ব ডেডিকেটেড শ্রোতা থ্রেড ধারণ করে এবং পরিচালনা করে। এই থ্রেডটি requestChannel এফএমকিউ থেকে অনুরোধ গ্রহণ করে, অনুমান সম্পাদন করে, তারপর resultChannel এফএমকিউ-এর মাধ্যমে ফলাফল প্রদান করে। এই থ্রেড এবং IBurstContext অবজেক্টের মধ্যে থাকা অন্যান্য সমস্ত সংস্থান স্বয়ংক্রিয়ভাবে প্রকাশিত হয় যখন burst এর ক্লায়েন্ট IBurstContext এর রেফারেন্স হারায়।

বিকল্পভাবে, আপনি IBurstContext এর নিজস্ব বাস্তবায়ন তৈরি করতে পারেন যা বুঝতে পারে যে কীভাবে IPreparedModel::configureExecutionBurst এ পাস করা requestChannel এবং resultChannel FMQ-এর মাধ্যমে বার্তা পাঠাতে এবং গ্রহণ করতে হয়।

বার্স্ট ইউটিলিটি ফাংশনগুলি ExecutionBurstServer.h এ পাওয়া যায়।

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

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