LiteRT ऐक्सेलरेटर टेस्ट सुइट (एटीएस)

LiteRT ऐक्सलरेटर टेस्ट सुइट (एटीएस) एक ऐसा टूल है जिसका इस्तेमाल, LiteRT फ़्रेमवर्क के साथ इंटिग्रेट किए गए कस्टम ऐक्सलरेटर के फ़ंक्शन की जांच करने और उनकी परफ़ॉर्मेंस को मेज़र करने के लिए किया जाता है.

खास जानकारी और मुख्य फ़ंक्शन

एटीएस का मुख्य काम, टारगेट ऐक्सलरेटर के ख़िलाफ़ पहले से तय किए गए मशीन लर्निंग मॉडल को लागू करना है. साथ ही, नतीजों की तुलना LiteRT के स्टैंडर्ड सीपीयू बैकएंड से करना है.

  • पुष्टि करना: यह सुइट, संख्यात्मक पुष्टि करता है. इसके लिए, यह ऐक्सलरेटर से मिले आउटपुट टेंसर (ऐक्टिवेशन) की तुलना, सीपीयू के भरोसेमंद बैकएंड से मिले आउटपुट टेंसर से करता है. इससे यह पक्का किया जाता है कि ऐक्सलरेटर को लागू करने के दौरान, ज़रूरी बारीकी और सटीकता बनी रहे.
  • परफ़ॉर्मेंस मेट्रिक: यह परफ़ॉर्मेंस की ज़रूरी जानकारी को अपने-आप कैप्चर और रिकॉर्ड करता है. इसमें लेटेंसी और अन्य काम की मेट्रिक शामिल हैं. यह जानकारी उपयोगकर्ता के लिए उपलब्ध कराई जाती है.
  • टेस्ट को लागू करना: आम तौर पर, टेस्ट को टारगेट डिवाइस (जैसे कि Android फ़ोन) पर लागू किया जाता है.इन्हें शेल स्क्रिप्ट रैपर मैनेज करता है. यह रैपर, adb (Android Debug Bridge) टूल का इस्तेमाल करके, फ़ाइल ट्रांसफ़र और सेटअप को मैनेज करता है.

टेस्ट डेटा (मॉडल)

ATS सुइट, टेस्ट डेटा के तौर पर, सबसे ज़्यादा इस्तेमाल किए जाने वाले .tflite मॉडल के कलेक्शन का इस्तेमाल करता है. इनपुट डेटा, डेटा टाइप के आधार पर रैंडम तरीके से जनरेट होता है. इसे ज़रूरत के हिसाब से सीड किया जा सकता है.

शामिल किए गए मॉडल

जांच के लिए, ये मॉडल अपने-आप शामिल हो जाते हैं और डाउनलोड हो जाते हैं. हालांकि, इनमें बदलाव हो सकता है:

  • hf_all_minilm_l6_v2
  • hf_mobilevit_small
  • qai_hub_midas
  • qai_hub_real_esrgan_x4plus
  • torchvision_mobilenet_v2
  • torchvision_resnet18
  • torchvision_squeezenet1_1
  • u2net_lite
  • whisper_tiny_decoder
  • whisper_tiny_encoder
  • yamnet
  • yolo11n

मैन्युअल तरीके से मॉडल वापस पाना

bazel run के दौरान मॉडल अपने-आप डाउनलोड हो जाते हैं. हालांकि, wget का इस्तेमाल करके, मॉडल के पूरे सेट को मैन्युअल तरीके से वापस लाया जा सकता है:

wget -p -O <target_file> https://storage.googleapis.com/litert/ats_models.tar.gz

Bazel की मदद से एटीएस सुइट तय करना

litert_define_ats Bazel मैक्रो का इस्तेमाल करके, एटीएस टेस्टिंग के टारगेट को कॉन्फ़िगर और तय करें. यह टारगेट, उनके ऐक्सलरेटर के हिसाब से तय किया जाता है.

यह मैक्रो, अपने-आप चलने वाले दो टारगेट बनाता है:

  1. स्टैंडर्ड डिवाइस पर मौजूद जेआईटी टेस्ट (लागू करने और पुष्टि करने के लिए).
  2. होस्ट कंपाइलेशन के लिए, एओटी "सिर्फ़ कंपाइल करें" मोड का टेस्ट.

उदाहरण litert_define_ats इस्तेमाल करने का तरीका

इस उदाहरण में, example नाम वाले बैकएंड के साथ काम करने वाले ऐक्सलरेटर के लिए, example_ats नाम के एटीएस सुइट को तय किया गया है:

# Emits aot-mode and jit-mode test targets, one for running compilation test on host
# and another for running JIT and inference on device
# These targets are named with their respective suffix attribute.
litert_define_ats(
    name = "example_ats",
    backend = "example",
    compile_only_suffix = "_aot",
    do_register = [
        "*mobilenet*",
    ],
    extra_flags = ["--limit=1"],
    jit_suffix = "",
)

प्लान लागू करना

Android के लिए टारगेट किए गए स्टैंडर्ड टेस्ट को लागू करने के लिए (जो सभी adb कार्रवाइयों को मैनेज करता है):

# Handles environment setup, and build + push of library and data dependencies to the device,
# executes the suite on the target.
bazel run -c opt --config=android_arm64 :example_ats

AOT कंपाइलेशन टेस्ट को लागू करने के लिए:

# Handle environment setup, and builds library dependencies for host platform.
# Executes the ats compile only flow. The "--compile_mode" flag is already
# bound to the program arguments.
bazel run :example_ats_aot

Linux Execution (Host)

Linux पर ATS को उसी मशीन पर चलाने के लिए जिस पर बिल्ड किया जा रहा है, उपयोगकर्ताओं को सीधे तौर पर :ats बाइनरी का इस्तेमाल करना होगा:

bazel run -c opt :ats

IoT Execution

आईओटी को लागू करने के लिए, उपयोगकर्ताओं को होस्ट पर बाइनरी बनानी होगी और उसे अपने डिवाइस पर मैन्युअल तरीके से पुश करना होगा.

कमांड-लाइन फ़्लैग

ats एक्ज़ीक्यूटेबल, टेस्टिंग और रिपोर्टिंग पर ज़्यादा कंट्रोल के लिए कई फ़्लैग स्वीकार करता है.

झंडा टाइप ब्यौरा
--backend std::string ज़रूरी है. जांच के दौरान, ऐक्सलरेटर के तौर पर किस LiteRT बैकएंड का इस्तेमाल करना है ("असल"). इसके विकल्प cpu, npu या gpu हैं.
--compile_mode bool अगर यह वैल्यू सही है, तो डिवाइस पर एक्ज़ीक्यूट करने के बजाय, वर्कस्टेशन पर एओटी कंपाइलेशन का चरण पूरा किया जाता है. ध्यान दें: यह विकल्प, "aot" बिल्ड टारगेट से अपने-आप जुड़ जाता है. इसे अलग से सेट करने की ज़रूरत नहीं होती.
--models_out std::string यह डायरेक्ट्री का वह पाथ होता है जहां साइड-इफ़ेक्ट वाले सीरियल किए गए (कंपाइल किए गए) मॉडल सेव किए जाते हैं. यह सिर्फ़ AOT या JIT कंपाइलेशन के लिए काम का है.
--dispatch_dir std::string ऐक्सलरेटर की डिस्पैच लाइब्रेरी वाली डायरेक्ट्री का पाथ (एनपीयू के लिए ज़रूरी है).
--plugin_dir std::string ऐक्सलरेटर के कंपाइलर प्लगिन लाइब्रेरी वाली डायरेक्ट्री का पाथ (एनपीयू के लिए ज़रूरी है).
--soc_manufacturer std::string एओटी कंपाइलेशन के लिए, एसओसी मैन्युफ़ैक्चरर को टारगेट किया जाता है. यह एनपीयू कंपाइलेशन के लिए ज़रूरी है.
--soc_model std::string एओटी कंपाइलेशन के लिए टारगेट किया जाने वाला एसओसी मॉडल. यह एनपीयू कंपाइलेशन के लिए काम का है.
--iters_per_test size_t हर टेस्ट के लिए, दोहराव की संख्या. हर दोहराव में, अलग-अलग रैंडमाइज़्ड टेंसर डेटा होता है.
--max_ms_per_test int64_t टाइम आउट होने से पहले, हर टेस्ट को चलाने के लिए ज़्यादा से ज़्यादा समय (मिलीसेकंड में).
--fail_on_timeout bool अगर टेस्ट पूरा होने में ज़्यादा समय लगता है, तो क्या टेस्ट को फ़ेल माना जाना चाहिए.
--csv std::string CSV फ़ॉर्मैट में ज़्यादा जानकारी वाली रिपोर्ट सेव करने के लिए फ़ाइल पाथ.
--dump_report bool क्या पूरी रिपोर्ट की जानकारी को सीधे तौर पर उपयोगकर्ता के कंसोल आउटपुट में डंप करना है.
--data_seed std::optional<int> ग्लोबल डेटा जनरेट करने के लिए एक ही सीड.
--do_register std::vector<std::string> खास टेस्ट को साफ़ तौर पर शामिल करने के लिए, रेगुलर एक्सप्रेशन (उदाहरण के लिए, *mobilenet*).
--dont_register std::vector<std::string> कुछ टेस्ट को बाहर रखने के लिए, रेगुलर एक्सप्रेशन.
--extra_models std::vector<std::string> टेस्ट सुइट में जोड़ने के लिए, डायरेक्ट्री या मॉडल फ़ाइलों की सूची (ज़रूरी नहीं).
--limit int32_t रजिस्टर किए गए और चलाए गए टेस्ट की कुल संख्या को सीमित करें.
--quiet bool टेस्ट रन के दौरान लॉगिंग आउटपुट को कम करें.

एटीएस के लिए litert_device_script बिल्ड यूटिलिटी का इस्तेमाल करना

एटीएस के टारगेट किए गए उपयोगकर्ताओं के लिए, अपने-आप लागू होने वाले टेस्ट में एक शेल एंट्री पॉइंट शामिल होता है. यह एनवायरमेंट सेटअप और ज़रूरी लाइब्रेरी को पुश करने का काम करता है. ऐसा तब होता है, जब टारगेट डिवाइस उस होस्ट से अलग होता है जिस पर बिल्ड पूरा किया गया था. उदाहरण के लिए, adb push.

यह सुविधा, litert_device_script की मदद से सामान्य तौर पर उपलब्ध कराई जाती है. एटीएस, litert_device_script की मदद से यूटिलिटी बनाता है. इस सुविधा को ऐक्सेस करने के लिए, ऐक्सेलरेटर को रजिस्टर करना होगा. ats के साथ काम करने के अलावा, इन यूटिलिटी का इस्तेमाल अकेले भी किया जा सकता है. इनकी मदद से, cc_binary और cc_test को सिम्युलेट किया जा सकता है. इन्हें ऐसे डिवाइस पर एक्ज़ीक्यूट किया जाता है जो बिल्ड होस्ट से अलग होता है और जिसे पुश की गई डिपेंडेंसी की ज़रूरत होती है.

बैकएंड रजिस्ट्रेशन

litert_device_script (और इसलिए एटीएस) के साथ इस्तेमाल करने के लिए, किसी नए ऐक्सलरेटर को चालू करने के लिए, उसकी ज़रूरी लाइब्रेरी को litert_device_common.bzl Bazel फ़ाइल में रजिस्टर करना होगा. रजिस्ट्रेशन, यूनीक "बैकएंड" नाम पर आधारित होता है. यह नाम, उन लाइब्रेरी के सेट से मैप होता है जिन्हें बनाया जा सकता है या पहले से कंपाइल किया जा सकता है. इन लाइब्रेरी की ज़रूरत, LiteRT को उस ऐक्सलरेटर के साथ काम करने के लिए होती है.

रजिस्ट्रेशन के चरण

  1. BackendSpec फ़ंक्शन तय करें: एक ऐसा फ़ंक्शन बनाएं जो आपके नए ऐक्सलरेटर की खास जानकारी वाला डिक्शनरी दिखाता हो.

  2. लाइब्रेरी तय करें (libs): यह टपल की एक सूची है. इसमें शेयर की गई लाइब्रेरी के लिए Bazel टारगेट पाथ और डिवाइस लिंकर को इसे ढूंढने के लिए ज़रूरी एनवायरमेंट वैरिएबल (LD_LIBRARY_PATH) के बारे में जानकारी दी गई है.

    • Dispatch Library: रनटाइम एक्ज़ीक्यूशन के लिए ज़रूरी है.
    • कंपाइलर प्लगिन लाइब्रेरी: एओटी कंपाइलेशन मोड के लिए ज़रूरी है.
  3. लाइब्रेरी के नाम तय करें (plugin, dispatch): प्लगिन और डिसपैच लाइब्रेरी के फ़ाइल नाम दें.

  4. स्पेक रजिस्टर करें: अपने नए स्पेक फ़ंक्शन को मुख्य _Specs फ़ंक्शन में मर्ज करें, ताकि यह यूनीक बैकएंड आईडी से उपलब्ध हो सके.

रजिस्ट्रेशन का उदाहरण (_ExampleSpec)

litert_device_common.bzl का यह कोड दिखाता है कि "example" ऐक्सिलरेटर कैसे रजिस्टर किया जाता है:

def _ExampleSpec():
    return {
        # The unique backend ID
        "example": BackendSpec(
            id = "example",
            libs = [
                # Dispatch Library and how to find it on device
                ("//third_party/odml/litert/litert/vendors/examples:libLiteRtDispatch_Example.so", "LD_LIBRARY_PATH"),
                # Compiler Plugin Library
                ("//third_party/odml/litert/litert/vendors/examples:libLiteRtCompilerPlugin_Example.so", "LD_LIBRARY_PATH"),
            ],
            plugin = "libLiteRtCompilerPlugin_Example.so",
            dispatch = "libLiteRtDispatch_Example.so",
        ),
    }

# ... (Other specs are defined here)

def _Specs(name):
    # Your new spec function must be included here
    return (_QualcommSpec() | _GoogleTensorSpec() | _MediatekSpec() | _CpuSpec() | _GpuSpec() | _ExampleSpec())[name]

litert_device_exec की मदद से रजिस्ट्रेशन का फ़ायदा पाना

रजिस्टर करने के बाद, नए backend_id के साथ litert_device_exec और इससे जुड़े मैक्रो का इस्तेमाल करें. यह मैक्रो, ज़रूरी लाइब्रेरी और बताई गई डेटा फ़ाइलों को टारगेट बाइनरी के साथ अपने-आप बंडल कर देता है.

cc_binary(
    name = "example_bin",
    srcs = ["example_bin.cc"],
)

litert_device_exec(
    name = "example_bin_device",
    backend_id = "example",  # Uses the libraries registered under "example"
    data = [
        "//third_party/odml/litert/litert/test:testdata/constant_output_tensor.tflite",
    ],
    target = ":example_bin",
)

इस टारगेट (bazel run ... :example_bin_device) को चलाने पर:

  1. example_bin C++ बाइनरी बनाएं.
  2. डिवाइस पर बाइनरी, libLiteRtDispatch_Example.so, libLiteRtCompilerPlugin_Example.so, और .tflite फ़ाइल को पुश करें.
  3. adb shell का इस्तेमाल करके बाइनरी को एक्ज़ीक्यूट करें.

डिवाइस पाथ के बारे में जानकारी: डिवाइस पर फ़ाइलों की कैननिकल लोकेशन, Bazel के रनफ़ाइल ट्री की तरह होती है. खास तौर पर, /data/local/tmp/runfiles/runfiles_relative_path. डिवाइस स्क्रिप्ट, डाइनैमिक लिंकर के लिए सही पाथ सेट करने का काम अपने-आप करती है.

कंपाइलेशन मोड (एओटी)

जिन ऐक्सेलरेटर में पहले से कंपाइल करने (एओटी) की सुविधा होती है उनके लिए, एटीएस को "कंपाइल मोड" में चलाया जा सकता है.

  • मकसद: इस मोड को वर्कस्टेशन (होस्ट मशीन) पर चलाने के लिए डिज़ाइन किया गया है, न कि टारगेट डिवाइस पर. यह दिए गए टारगेट हार्डवेयर के लिए मॉडल कंपाइल करता है. हालांकि, उन्हें एक्ज़ीक्यूट नहीं करता.
  • आउटपुट: कंपाइल किए गए सभी मॉडल, वर्कस्टेशन पर मौजूद किसी डायरेक्ट्री में आउटपुट किए जाते हैं.
  • ऐक्टिवेशन: एटीएस बिल्ड मैक्रो, एओटी के लिए एक खास टारगेट जनरेट करेंगे. यहां लाइब्रेरी, होस्ट प्लैटफ़ॉर्म के लिए बनाई जाती हैं. इस फ़्लो को --compile_mode फ़्लैग वाली किसी भी बाइनरी पर चालू किया जा सकता है. हालांकि, यह एओटी बिल्ड के तर्कों से अपने-आप जुड़ जाता है.

आने वाले समय में होने वाले बदलाव

इस सुइट को और बेहतर बनाने का प्लान है. इसमें पूरे मॉडल के साथ-साथ, सिंगल ऑपरेशन (ऑप्स) के लिए खास टेस्ट शामिल किए जाएंगे.