Suite de tests (ATS) de l'accélérateur LiteRT

La suite de tests de l'accélérateur LiteRT (ATS) est un outil complet utilisé pour valider la correction fonctionnelle et mesurer les performances des implémentations d'accélérateur personnalisées intégrées au framework LiteRT.

Présentation et fonctionnalités de base

La fonction principale d'ATS est d'exécuter des modèles de machine learning prédéfinis sur un accélérateur cible et de comparer les résultats avec le backend CPU standard de LiteRT.

  • Validation : la suite effectue une validation numérique en comparant les Tensors de sortie (activations) produits par l'accélérateur à ceux produits par le backend CPU connu pour être fiable. Cela permet de s'assurer que l'implémentation de l'accélérateur maintient la précision et l'exactitude requises.
  • Métriques de performances : capture et enregistre automatiquement les détails essentiels sur les performances, y compris la latence et d'autres métriques pertinentes, qui sont mises à la disposition de l'utilisateur.
  • Exécution : les tests sont généralement exécutés sur un appareil cible (par exemple, un téléphone Android) et sont gérés par un wrapper de script shell qui gère les transferts de fichiers et la configuration à l'aide de l'outil adb (Android Debug Bridge).

Données de test (modèles)

La suite ATS utilise une collection de modèles .tflite largement utilisés comme données de test. Les données d'entrée sont générées de manière aléatoire en fonction du type de données et peuvent être initialisées si nécessaire.

Modèles inclus

Les modèles suivants sont automatiquement inclus et téléchargés pour les tests (sous réserve de modifications) :

  • 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

Récupération manuelle de modèles

Bien que les modèles soient téléchargés automatiquement lors d'un bazel run, vous pouvez récupérer manuellement l'ensemble des modèles à l'aide de wget :

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

Définir une suite ATS avec Bazel

Utilisez la macro Bazel litert_define_ats pour configurer et définir une cible de test ATS spécifique à leur accélérateur.

La macro crée automatiquement deux cibles exécutables :

  1. Le test JIT sur l'appareil standard (pour l'exécution et la validation).
  2. Un test en mode "compile only" AOT dédié (pour la compilation hôte).

Exemple d'utilisation de litert_define_ats

L'exemple définit une suite ATS nommée example_ats pour un accélérateur dont le nom de backend est example :

# 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 = "",
)

Exécution

Pour exécuter le test standard ciblé pour Android (qui gère toutes les opérations 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

Pour exécuter le test de compilation 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

Exécution Linux (hôte)

Pour l'exécution Linux, où ATS est exécuté sur la même machine que celle qui effectue la compilation, les utilisateurs devront utiliser directement le binaire :ats :

bazel run -c opt :ats

Exécution IoT

Pour l'exécution de l'IoT, les utilisateurs devront créer le fichier binaire sur l'hôte et le transférer manuellement sur leur appareil.

Indicateurs de ligne de commande

L'exécutable ats accepte plusieurs indicateurs pour un contrôle précis des tests et des rapports.

Option Type Description
--backend std::string Obligatoire. Backend LiteRT à utiliser comme accélérateur en cours de test (l'accélérateur "réel"). Les options sont cpu, npu ou gpu.
--compile_mode bool Si la valeur est "true", l'étape de compilation AOT est exécutée sur la station de travail au lieu de l'être sur l'appareil. REMARQUE : Cette option est automatiquement liée à la cible de compilation "aot" et n'a pas besoin d'être définie explicitement.
--models_out std::string Chemin d'accès au répertoire dans lequel les modèles sérialisés (compilés) à effets secondaires sont enregistrés. Ne concerne que la compilation AOT ou JIT.
--dispatch_dir std::string Chemin d'accès au répertoire contenant la bibliothèque de répartition de l'accélérateur (pertinent pour le NPU).
--plugin_dir std::string Chemin d'accès au répertoire contenant la bibliothèque du plug-in de compilation de l'accélérateur (pertinent pour l'unité de traitement neuronal).
--soc_manufacturer std::string Fabricant du SoC à cibler pour la compilation AOT (pertinent pour la compilation NPU).
--soc_model std::string Modèle SOC à cibler pour la compilation AOT (pertinent pour la compilation NPU).
--iters_per_test size_t Nombre d'itérations à exécuter par test, chacune avec des données de Tensor aléatoires différentes.
--max_ms_per_test int64_t Temps maximal en millisecondes pour exécuter chaque test avant un délai d'expiration.
--fail_on_timeout bool Indique si le test doit échouer en cas de délai d'exécution dépassé.
--csv std::string Chemin d'accès au fichier pour enregistrer le rapport détaillé au format CSV.
--dump_report bool Indique s'il faut vider tous les détails du rapport directement dans la sortie de la console de l'utilisateur.
--data_seed std::optional<int> Une seule graine pour la génération de données mondiales.
--do_register std::vector<std::string> Expression(s) régulière(s) pour inclure explicitement des tests spécifiques (par exemple, *mobilenet*).
--dont_register std::vector<std::string> Expression(s) régulière(s) permettant d'exclure des tests spécifiques.
--extra_models std::vector<std::string> Liste facultative de répertoires ou de fichiers de modèle à ajouter à la suite de tests.
--limit int32_t Limitez le nombre total de tests enregistrés et exécutés.
--quiet bool Minimisez la sortie de journalisation pendant l'exécution du test.

Utiliser les utilitaires de compilation litert_device_script pour ATS

Les cibles ATS que les utilisateurs exécutent automatiquement incluent un point d'entrée shell qui gère toute la configuration de l'environnement et tout transfert des bibliothèques requises lorsque l'appareil cible diffère de l'hôte sur lequel la compilation a été effectuée (par exemple, adb push).

Cette fonctionnalité est fournie de manière générique par le biais des utilitaires litert_device_script que les compilations ATS utilisent en arrière-plan. Les accélérateurs doivent suivre une procédure d'enregistrement pour accéder à cette fonctionnalité de compilation. En plus de la prise en charge de ats, ces utilitaires peuvent être utilisés de manière autonome pour simuler cc_binary et cc_test destinés à être exécutés sur un appareil différent de l'hôte de compilation nécessitant des dépendances transférées.

Enregistrement du backend

Pour activer un nouvel accélérateur à utiliser avec litert_device_script (et donc ATS), ses bibliothèques requises doivent être enregistrées dans le fichier Bazel litert_device_common.bzl. L'enregistrement est basé sur un nom de backend unique qui correspond à un ensemble de bibliothèques compilables ou précompilées nécessaires pour que LiteRT fonctionne avec cet accélérateur.

Étapes d'inscription

  1. Définissez une fonction BackendSpec : créez une fonction qui renvoie un dictionnaire contenant la spécification de votre nouvel accélérateur.

  2. Spécifier les bibliothèques (libs) : il s'agit d'une liste de tuples détaillant le chemin d'accès cible Bazel pour la bibliothèque partagée et la variable d'environnement (LD_LIBRARY_PATH) requise pour que l'outil Device Linker puisse la trouver.

    • Bibliothèque Dispatch : requise pour l'exécution du runtime.
    • Bibliothèque de plug-ins du compilateur : requise pour le mode de compilation AOT.
  3. Spécifiez les noms des bibliothèques (plugin, dispatch) : indiquez les noms de fichier des bibliothèques de plug-in et de répartition.

  4. Enregistrez la spécification : fusionnez votre nouvelle fonction de spécification dans la fonction _Specs principale pour la rendre disponible par son ID de backend unique.

Exemple d'inscription (_ExampleSpec)

Le code suivant de litert_device_common.bzl montre comment l'accélérateur "example" est enregistré :

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]

Exploiter l'enregistrement avec litert_device_exec

Une fois enregistré, utilisez litert_device_exec et les macros associées avec le nouveau backend_id. Cette macro regroupe automatiquement les bibliothèques requises et tous les fichiers de données spécifiés avec le binaire cible.

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",
)

L'exécution de cette cible (bazel run ... :example_bin_device) :

  1. Créez le binaire C++ example_bin.
  2. Transférez le fichier binaire libLiteRtDispatch_Example.so, libLiteRtCompilerPlugin_Example.so et le fichier .tflite sur l'appareil.
  3. Exécutez le binaire à l'aide de adb shell.

Remarque sur les chemins d'accès aux appareils : L'emplacement canonique des fichiers sur l'appareil reflète l'arborescence des fichiers d'exécution de Bazel, en particulier /data/local/tmp/runfiles/runfiles_relative_path. Le script de l'appareil gère automatiquement la définition des chemins appropriés pour l'éditeur de liens dynamique.

Mode de compilation (AOT)

Pour les accélérateurs qui prennent en charge une étape de compilation anticipée (AOT), ATS peut être exécuté dans un mode de compilation dédié.

  • Objectif : Ce mode est conçu pour être exécuté sur une station de travail (machine hôte), et non sur l'appareil cible. Il compile les modèles pour le matériel cible spécifié sans les exécuter.
  • Sortie : tous les modèles compilés sont placés dans un répertoire désigné sur le poste de travail.
  • Activation : les macros de compilation ATS émettent une cible spécifique pour aot où les bibliothèques sont compilées pour la plate-forme hôte. Ce flux peut être activé sur n'importe quel binaire avec l'indicateur --compile_mode, mais il est automatiquement lié aux arguments de la compilation AOT.

Expansion future

La suite devrait être étendue pour inclure des tests dédiés aux opérations uniques, en plus des modèles complets.