LiterRT এর সাথে NPU ত্বরণ

LiterRT আপনাকে বিক্রেতা-নির্দিষ্ট কম্পাইলার, রানটাইম বা লাইব্রেরি নির্ভরতা নেভিগেট করতে বাধ্য না করেই নিউরাল প্রসেসিং ইউনিট (NPU) ব্যবহার করার জন্য একটি ইউনিফাইড ইন্টারফেস প্রদান করে। NPU ত্বরণের জন্য LiterRT ব্যবহার রিয়েল-টাইম এবং বৃহৎ-মডেল ইনফারেন্সের জন্য কর্মক্ষমতা বৃদ্ধি করে এবং শূন্য-কপি হার্ডওয়্যার বাফার ব্যবহারের মাধ্যমে মেমরি কপিগুলিকে কমিয়ে দেয়।

শুরু করুন

শুরু করতে, NPU ওভারভিউ গাইডটি দেখুন:

  • ধ্রুপদী এমএল মডেলের জন্য , রূপান্তর, সংকলন এবং স্থাপনার ধাপগুলির জন্য নিম্নলিখিত বিভাগগুলি দেখুন।
  • বৃহৎ ভাষা মডেল (LLM) এর জন্য , আমাদের LiterRT-LM ফ্রেমওয়ার্ক ব্যবহার করুন:

উদাহরণস্বরূপ, NPU সমর্থন সহ LiterRT বাস্তবায়নের জন্য, নিম্নলিখিত ডেমো অ্যাপ্লিকেশনগুলি দেখুন:

এনপিইউ বিক্রেতারা

LiterRT নিম্নলিখিত বিক্রেতাদের সাথে NPU ত্বরণ সমর্থন করে:

কোয়ালকম এআই ইঞ্জিন ডাইরেক্ট

  • AOT এবং অন-ডিভাইস সংকলন এক্সিকিউশন পাথগুলি কম্পাইলড মডেল API এর মাধ্যমে সমর্থিত।
  • সেটআপের বিস্তারিত জানার জন্য Qualcomm AI Engine Direct দেখুন।

মিডিয়াটেক নিউরোপাইলট

  • AOT এবং JIT এক্সিকিউশন পাথগুলি কম্পাইলড মডেল API এর মাধ্যমে সমর্থিত।
  • সেটআপের বিস্তারিত জানার জন্য মিডিয়াটেক নিউরোপাইলট দেখুন।

NPU-এর জন্য মডেল রূপান্তর এবং কম্পাইল করুন

LiterRT-এর সাথে NPU অ্যাক্সিলারেশন ব্যবহার করার জন্য, মডেলগুলিকে LiterRT ফাইল ফর্ম্যাটে রূপান্তর করতে হবে এবং ডিভাইসে NPU ব্যবহারের জন্য কম্পাইল করতে হবে। আপনি LiterRT AOT (সময়ের আগে) কম্পাইলার ব্যবহার করে মডেলগুলিকে একটি AI প্যাকে কম্পাইল করতে পারেন, যা আপনার কম্পাইল করা মডেলগুলিকে ডিভাইস-টার্গেটিং কনফিগারেশনের সাথে একত্রিত করে। এটি যাচাই করে যে মডেলগুলি ডিভাইসগুলিতে সঠিকভাবে পরিবেশিত হচ্ছে কিনা তা নির্ভর করে নির্দিষ্ট SoC-এর জন্য সজ্জিত বা অপ্টিমাইজ করা হয়েছে কিনা তার উপর।

মডেলগুলি রূপান্তর এবং সংকলন করার পরে, আপনি Play for On-device AI (PODAI) ব্যবহার করে Google Play-তে মডেলগুলি আপলোড করতে পারেন এবং অন-ডিমান্ড AI ফ্রেমওয়ার্কের মাধ্যমে ডিভাইসগুলিতে মডেলগুলি সরবরাহ করতে পারেন।

NPU-এর জন্য মডেল রূপান্তর এবং সংকলনের জন্য একটি এন্ড-টু-এন্ড গাইডের জন্য LiterRT AOT সংকলন নোটবুক ব্যবহার করুন।

[শুধুমাত্র AOT] Play AI প্যাক দিয়ে স্থাপন করুন

মডেলটি রূপান্তর করে একটি AI প্যাক কম্পাইল করার পরে, Google Play-তে AI প্যাক স্থাপন করতে নিম্নলিখিত পদক্ষেপগুলি অনুসরণ করুন।

গ্রেডল প্রকল্পে এআই প্যাকগুলি আমদানি করুন

গ্র্যাডেল প্রজেক্টের রুট ডিরেক্টরিতে AI প্যাক(গুলি) কপি করুন। উদাহরণস্বরূপ:

my_app/
    ...
    ai_packs/
        my_model/...
        my_model_mtk/...

প্রতিটি AI প্যাক Gradle বিল্ড কনফিগারেশনে যোগ করুন:

// my_app/ai_packs/my_model/build.gradle.kts

plugins { id("com.android.ai-pack") }

aiPack {
  packName = "my_model"  // ai pack dir name
  dynamicDelivery { deliveryType = "on-demand" }
}

// Add another build.gradle.kts for my_model_mtk/ as well

প্রকল্পে NPU রানটাইম লাইব্রেরি যোগ করুন

AOT এর জন্য littert_npu_runtime_libraries.zip অথবা JIT এর জন্য littert_npu_runtime_libraries_jit.zip ডাউনলোড করুন এবং প্রকল্পের রুট ডিরেক্টরিতে এটি আনপ্যাক করুন:

my_app/
    ...
    litert_npu_runtime_libraries/
        mediatek_runtime/...
        qualcomm_runtime_v69/...
        qualcomm_runtime_v73/...
        qualcomm_runtime_v75/...
        qualcomm_runtime_v79/...
        qualcomm_runtime_v81/...
        fetch_qualcomm_library.sh

NPU সাপোর্ট লাইব্রেরি ডাউনলোড করতে স্ক্রিপ্টটি চালান। উদাহরণস্বরূপ, Qualcomm NPU গুলির জন্য নিম্নলিখিতটি চালান:

$ ./litert_npu_runtime_libraries/fetch_qualcomm_library.sh

গ্র্যাডেল কনফিগারেশনে AI প্যাক এবং NPU রানটাইম লাইব্রেরি যোগ করুন

জেনারেট করা AI প্যাকগুলি থেকে device_targeting_configuration.xml মূল অ্যাপ মডিউলের ডিরেক্টরিতে কপি করুন। তারপর settings.gradle.kts আপডেট করুন:

// my_app/setting.gradle.kts

...

// [AOT only]
// AI Packs
include(":ai_packs:my_model")
include(":ai_packs:my_model_mtk")

// NPU runtime libraries
include(":litert_npu_runtime_libraries:runtime_strings")

include(":litert_npu_runtime_libraries:mediatek_runtime")
include(":litert_npu_runtime_libraries:qualcomm_runtime_v69")
include(":litert_npu_runtime_libraries:qualcomm_runtime_v73")
include(":litert_npu_runtime_libraries:qualcomm_runtime_v75")
include(":litert_npu_runtime_libraries:qualcomm_runtime_v79")
include(":litert_npu_runtime_libraries:qualcomm_runtime_v81")

build.gradle.kts আপডেট করুন :

// my_app/build.gradle.kts

android {
 ...

 defaultConfig {
    ...

    // API level 31+ is required for NPU support.
    minSdk = 31

    // NPU only supports arm64-v8a
    ndk { abiFilters.add("arm64-v8a") }
    // Needed for Qualcomm NPU runtime libraries
    packaging { jniLibs { useLegacyPackaging = true } }
  }

  // Device targeting
  bundle {
      deviceTargetingConfig = file("device_targeting_configuration.xml")
      deviceGroup {
        enableSplit = true // split bundle by #group
        defaultGroup = "other" // group used for standalone APKs
      }
  }

  // [AOT Only]
  // AI Packs
  assetPacks.add(":ai_packs:my_model")
  assetPacks.add(":ai_packs:my_model_mtk")

  // NPU runtime libraries
  dynamicFeatures.add(":litert_npu_runtime_libraries:mediatek_runtime")
  dynamicFeatures.add(":litert_npu_runtime_libraries:qualcomm_runtime_v69")
  dynamicFeatures.add(":litert_npu_runtime_libraries:qualcomm_runtime_v73")
  dynamicFeatures.add(":litert_npu_runtime_libraries:qualcomm_runtime_v75")
  dynamicFeatures.add(":litert_npu_runtime_libraries:qualcomm_runtime_v79")
  dynamicFeatures.add(":litert_npu_runtime_libraries:qualcomm_runtime_v81")
}

dependencies {
  // Dependencies for strings used in the runtime library modules.
  implementation(project(":litert_npu_runtime_libraries:runtime_strings"))
  ...
}

[শুধুমাত্র AOT] অন-ডিমান্ড ডিপ্লয়মেন্ট ব্যবহার করুন

build.gradle.kts ফাইলে কনফিগার করা Android AI Pack বৈশিষ্ট্যটি ব্যবহার করে, ডিভাইসের ক্ষমতা পরীক্ষা করুন এবং সক্ষম ডিভাইসগুলিতে NPU ব্যবহার করুন, ফলব্যাক হিসেবে GPU এবং CPU ব্যবহার করুন:

val env = Environment.create(BuiltinNpuAcceleratorProvider(context))

val modelProvider = AiPackModelProvider(
    context, "my_model", "model/my_model.tflite") {
    if (NpuCompatibilityChecker.Qualcomm.isDeviceSupported())
      setOf(Accelerator.NPU) else setOf(Accelerator.CPU, Accelerator.GPU)
}
val mtkModelProvider = AiPackModelProvider(
    context, "my_model_mtk", "model/my_model_mtk.tflite") {
    if (NpuCompatibilityChecker.Mediatek.isDeviceSupported())
      setOf(Accelerator.NPU) else setOf()
}
val modelSelector = ModelSelector(modelProvider, mtkModelProvider)
val model = modelSelector.selectModel(env)

val compiledModel = CompiledModel.create(
    model.getPath(),
    CompiledModel.Options(model.getCompatibleAccelerators()),
    env,
)

JIT মোডের জন্য CompiledModel তৈরি করুন

val env = Environment.create(BuiltinNpuAcceleratorProvider(context))

val compiledModel = CompiledModel.create(
    "model/my_model.tflite",
    CompiledModel.Options(Accelerator.NPU),
    env,
)

কোটলিনে LiterRT ব্যবহার করে NPU সম্পর্কে অনুমান

NPU অ্যাক্সিলারেটর ব্যবহার শুরু করতে, কম্পাইলড মডেল ( CompiledModel ) তৈরি করার সময় NPU প্যারামিটারটি পাস করুন।

নিম্নলিখিত কোড স্নিপেটটি কোটলিনে সম্পূর্ণ প্রক্রিয়াটির একটি মৌলিক বাস্তবায়ন দেখায়:

val inputBuffers = model.createInputBuffers()
val outputBuffers = model.createOutputBuffers()

inputBuffers[0].writeFloat(FloatArray(data_size) { data_value })
model.run(inputBuffers, outputBuffers)
val outputFloatArray = outputBuffers[0].readFloat()

inputBuffers.forEach { it.close() }
outputBuffers.forEach { it.close() }
model.close()

C++ এ LiterRT ব্যবহার করে NPU সম্পর্কে অনুমান

নির্ভরতা তৈরি করুন

C++ ব্যবহারকারীদের LiteRT NPU ত্বরণের মাধ্যমে অ্যাপ্লিকেশনের নির্ভরতা তৈরি করতে হবে। cc_binary নিয়ম যা মূল অ্যাপ্লিকেশন লজিক (যেমন, main.cc ) প্যাকেজ করে তার জন্য নিম্নলিখিত রানটাইম উপাদানগুলির প্রয়োজন:

  • LiterRT C API শেয়ার্ড লাইব্রেরি : data অ্যাট্রিবিউটে অবশ্যই LiterRT C API শেয়ার্ড লাইব্রেরি ( //litert/c:litert_runtime_c_api_shared_lib ) এবং NPU ( //litert/vendors/qualcomm/dispatch:dispatch_api_so ) এর জন্য বিক্রেতা-নির্দিষ্ট ডিসপ্যাচ শেয়ার্ড অবজেক্ট অন্তর্ভুক্ত থাকতে হবে।
  • NPU-নির্দিষ্ট ব্যাকএন্ড লাইব্রেরি : উদাহরণস্বরূপ, অ্যান্ড্রয়েড হোস্টের জন্য Qualcomm AI RT (QAIRT) লাইব্রেরি (যেমন libQnnHtp.so , libQnnHtpPrepare.so ) এবং সংশ্লিষ্ট Hexagon DSP লাইব্রেরি ( libQnnHtpV79Skel.so )। এটি নিশ্চিত করে যে LiterRT রানটাইম NPU-তে গণনা অফলোড করতে পারে।
  • অ্যাট্রিবিউট ডিপেন্ডেন্সি : deps অ্যাট্রিবিউট লিংকগুলি প্রয়োজনীয় কম্পাইল-টাইম ডিপেন্ডেন্সির সাথে সংযুক্ত করে, যেমন LiterT এর টেনসর বাফার ( //litert/cc:litert_tensor_buffer ) এবং NPU ডিসপ্যাচ লেয়ারের API ( //litert/vendors/qualcomm/dispatch:dispatch_api )। এটি আপনার অ্যাপ্লিকেশন কোডকে LiteRT এর মাধ্যমে NPU এর সাথে ইন্টারঅ্যাক্ট করতে সক্ষম করে।
  • মডেল ফাইল এবং অন্যান্য সম্পদ : data অ্যাট্রিবিউটের মাধ্যমে অন্তর্ভুক্ত।

এই সেটআপটি আপনার কম্পাইল করা বাইনারিকে গতিশীলভাবে লোড করতে এবং ত্বরিত মেশিন লার্নিং ইনফারেন্সের জন্য NPU ব্যবহার করতে দেয়।

একটি NPU পরিবেশ সেট আপ করুন

কিছু NPU ব্যাকএন্ডের জন্য রানটাইম নির্ভরতা বা লাইব্রেরি প্রয়োজন হয়। কম্পাইল করা মডেল API ব্যবহার করার সময়, LiteRT একটি Environment অবজেক্টের মাধ্যমে এই প্রয়োজনীয়তাগুলি সংগঠিত করে। উপযুক্ত NPU লাইব্রেরি বা ড্রাইভার খুঁজে পেতে নিম্নলিখিত কোডটি ব্যবহার করুন:

// Provide a dispatch library directory (following is a hypothetical path) for the NPU
std::vector<Environment::Option> environment_options = {
    {
      Environment::OptionTag::DispatchLibraryDir,
      "/usr/lib64/npu_dispatch/"
    }
};

LITERT_ASSIGN_OR_RETURN(auto env, Environment::Create(absl::MakeConstSpan(environment_options)));

রানটাইম ইন্টিগ্রেশন

নিম্নলিখিত কোড স্নিপেটটি C++ এ সম্পূর্ণ প্রক্রিয়াটির একটি মৌলিক বাস্তবায়ন দেখায়:

// 1. Load the model that has NPU-compatible ops
LITERT_ASSIGN_OR_RETURN(auto model, Model::Load("mymodel_npu.tflite"));

// 2. Create a compiled model with NPU acceleration
//    See following section on how to set up NPU environment
LITERT_ASSIGN_OR_RETURN(auto compiled_model,
  CompiledModel::Create(env, model, kLiteRtHwAcceleratorNpu));

// 3. Allocate I/O buffers
LITERT_ASSIGN_OR_RETURN(auto input_buffers, compiled_model.CreateInputBuffers());
LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// 4. Fill model inputs (CPU array -> NPU buffers)
float input_data[] = { /* your input data */ };
input_buffers[0].Write<float>(absl::MakeConstSpan(input_data, /*size*/));

// 5. Run inference
compiled_model.Run(input_buffers, output_buffers);

// 6. Access model output
std::vector<float> data(output_data_size);
output_buffers[0].Read<float>(absl::MakeSpan(data));

NPU ত্বরণ সহ শূন্য-অনুলিপি

জিরো-কপি ব্যবহার করলে একটি NPU সরাসরি তার নিজস্ব মেমোরিতে ডেটা অ্যাক্সেস করতে পারে, CPU-কে স্পষ্টভাবে সেই ডেটা কপি করার প্রয়োজন হয় না। CPU মেমোরিতে এবং থেকে ডেটা কপি না করে, জিরো-কপি এন্ড-টু-এন্ড ল্যাটেন্সি উল্লেখযোগ্যভাবে হ্রাস করতে পারে।

নিচের কোডটি AHardwareBuffer সহ Zero-Copy NPU বাস্তবায়নের একটি উদাহরণ, যা সরাসরি NPU-তে ডেটা প্রেরণ করে। এই বাস্তবায়ন CPU মেমোরিতে ব্যয়বহুল রাউন্ড-ট্রিপ এড়ায়, ইনফারেন্স ওভারহেড উল্লেখযোগ্যভাবে হ্রাস করে।

// Suppose you have AHardwareBuffer* ahw_buffer

LITERT_ASSIGN_OR_RETURN(auto tensor_type, model.GetInputTensorType("input_tensor"));

LITERT_ASSIGN_OR_RETURN(auto npu_input_buffer, TensorBuffer::CreateFromAhwb(
    env,
    tensor_type,
    ahw_buffer,
    /* offset = */ 0
));

std::vector<TensorBuffer> input_buffers{npu_input_buffer};

LITERT_ASSIGN_OR_RETURN(auto output_buffers, compiled_model.CreateOutputBuffers());

// Execute the model
compiled_model.Run(input_buffers, output_buffers);

// Retrieve the output (possibly also an AHWB or other specialized buffer)
auto ahwb_output = output_buffers[0].GetAhwb();

একাধিক NPU অনুমানের শৃঙ্খল

জটিল পাইপলাইনের জন্য, আপনি একাধিক NPU ইনফারেন্স চেইন করতে পারেন। যেহেতু প্রতিটি ধাপে একটি অ্যাক্সিলারেটর-বান্ধব বাফার ব্যবহার করা হয়, তাই আপনার পাইপলাইন বেশিরভাগই NPU-পরিচালিত মেমোরিতে থাকে:

// compiled_model1 outputs into an AHWB
compiled_model1.Run(input_buffers, intermediate_buffers);

// compiled_model2 consumes that same AHWB
compiled_model2.Run(intermediate_buffers, final_outputs);

NPU-এর জাস্ট-ইন-টাইম কম্পাইলেশন ক্যাশিং

LiterRT .tflite মডেলের NPU just-in-time (JIT) সংকলন সমর্থন করে। JIT সংকলন বিশেষ করে সেই পরিস্থিতিতে কার্যকর হতে পারে যেখানে আগে থেকে মডেলটি সংকলন করা সম্ভব নয়।

তবে JIT সংকলনটি ব্যবহারকারী-প্রদত্ত মডেলটিকে NPU বাইটকোডে অন-ডিমান্ড নির্দেশাবলীতে অনুবাদ করার জন্য কিছু ল্যাটেন্সি এবং মেমোরি ওভারহেডের সাথে আসতে পারে। কর্মক্ষমতা প্রভাব কমাতে NPU সংকলন শিল্পকর্মগুলি ক্যাশে করা যেতে পারে।

যখন ক্যাশিং সক্ষম করা থাকে তখন LiterRT শুধুমাত্র প্রয়োজনের সময় মডেলটির পুনঃসংকলন ট্রিগার করবে, যেমন:

  • বিক্রেতার NPU কম্পাইলার প্লাগইন সংস্করণ পরিবর্তিত হয়েছে;
  • অ্যান্ড্রয়েড বিল্ড ফিঙ্গারপ্রিন্ট পরিবর্তন করা হয়েছে;
  • ব্যবহারকারী-প্রদত্ত মডেলটি পরিবর্তিত হয়েছে;
  • সংকলনের বিকল্পগুলি পরিবর্তিত হয়েছে।

NPU কম্পাইলেশন ক্যাশিং সক্ষম করার জন্য, পরিবেশ বিকল্পগুলিতে CompilerCacheDir পরিবেশ ট্যাগটি নির্দিষ্ট করুন। মানটি অ্যাপ্লিকেশনের একটি বিদ্যমান লেখার যোগ্য পথে সেট করতে হবে।

   const std::array environment_options = {
        litert::Environment::Option{
            /*.tag=*/litert::Environment::OptionTag::CompilerPluginLibraryDir,
            /*.value=*/kCompilerPluginLibSearchPath,
        },
        litert::Environment::Option{
            litert::Environment::OptionTag::DispatchLibraryDir,
            kDispatchLibraryDir,
        },
        // 'kCompilerCacheDir' will be used to store NPU-compiled model
        // artifacts.
        litert::Environment::Option{
            litert::Environment::OptionTag::CompilerCacheDir,
            kCompilerCacheDir,
        },
    };

    // Create an environment.
    LITERT_ASSERT_OK_AND_ASSIGN(
        auto environment, litert::Environment::Create(environment_options));

    // Load a model.
    auto model_path = litert::testing::GetTestFilePath(kModelFileName);
    LITERT_ASSERT_OK_AND_ASSIGN(auto model,
                                litert::Model::CreateFromFile(model_path));

    // Create a compiled model, which only triggers NPU compilation if
    // required.
    LITERT_ASSERT_OK_AND_ASSIGN(
        auto compiled_model, litert::CompiledModel::Create(
                                 environment, model, kLiteRtHwAcceleratorNpu));

ল্যাটেন্সি এবং মেমরি সাশ্রয়ের উদাহরণ:

NPU সংকলনের জন্য প্রয়োজনীয় সময় এবং মেমোরি বিভিন্ন কারণের উপর নির্ভর করে পরিবর্তিত হতে পারে, যেমন অন্তর্নিহিত NPU চিপ, ইনপুট মডেলের জটিলতা ইত্যাদি।

নিচের টেবিলে NPU কম্পাইলেশনের প্রয়োজন হলে রানটাইম ইনিশিয়ালাইজেশনের সময় এবং মেমোরি খরচ তুলনা করা হয়েছে, যেখানে ক্যাশিংয়ের কারণে কম্পাইলেশন এড়িয়ে যাওয়ার সম্ভাবনা তুলনা করা হয়েছে। একটি নমুনা ডিভাইসে আমরা নিম্নলিখিত তথ্য পাই:

টিএফলাইট মডেল NPU সংকলন সহ মডেল init ক্যাশেড সংকলন সহ মডেল init NPU সংকলনের সাথে init মেমরি ফুটপ্রিন্ট ক্যাশেড সংকলন সহ init মেমরি
টর্চভিশন_রেসনেট১৫২.টিফ্লাইট ৭৪৬৫.২২ মিলিসেকেন্ড ১৯৮.৩৪ মিলিসেকেন্ড ১৫২৫.২৪ মেগাবাইট ৩৫৫.০৭ মেগাবাইট
torchvision_lraspp_mobilenet_v3_large.tflite ১৫৯২.৫৪ মিলিসেকেন্ড ১৬৬.৪৭ মিলিসেকেন্ড ২৫৪.৯০ মেগাবাইট ৩৩.৭৮ মেগাবাইট

অন্য একটি ডিভাইসে আমরা নিম্নলিখিতগুলি পাই:

টিএফলাইট মডেল NPU সংকলন সহ মডেল init ক্যাশেড সংকলন সহ মডেল init NPU সংকলনের সাথে init মেমরি ফুটপ্রিন্ট ক্যাশেড সংকলন সহ init মেমরি
টর্চভিশন_রেসনেট১৫২.টিফ্লাইট ২৭৬৬.৪৪ মিলিসেকেন্ড ৩৭৯.৮৬ মিলিসেকেন্ড ৬৫৩.৫৪ মেগাবাইট ৫০১.২১ মেগাবাইট
torchvision_lraspp_mobilenet_v3_large.tflite ৭৮৪.১৪ মিলিসেকেন্ড ২৩১.৭৬ মিলিসেকেন্ড ১১৩.১৪ মেগাবাইট ৬৭.৪৯ মেগাবাইট