kazeia/DEPLOY_EXECUTORCH_NPU.md

5.3 KiB

Déploiement ExecuTorch + QNN NPU — OnePlus Pad 3

Procédure validée le 28 mars 2026

Prérequis

  • Tablette rootée (Magisk)
  • SELinux permissive (su -c 'setenforce 0')
  • DSP permissions ouvertes (boot script /data/adb/service.d/kazeia_dsp.sh)
  • QNN SDK 2.42 installé sur le PC : /opt/Kazeia/qnn_sdk_242/qairt/2.42.0.251225/
  • ExecuTorch compilé pour Android ARM64 : /opt/Kazeia/executorch/build-android/

Fichiers requis (TOUS obligatoires)

Fichier Source Rôle
qnn_llama_runner executorch/build-android/examples/qualcomm/oss_scripts/llama/ Runner LLM
libqnn_executorch_backend.so executorch/build-android/backends/qualcomm/ Backend ExecuTorch ↔ QNN
libQnnHtp.so qnn_sdk_242/.../lib/aarch64-android/ QNN HTP runtime
libQnnHtpV79Stub.so qnn_sdk_242/.../lib/aarch64-android/ Stub CPU → DSP
libQnnHtpV79Skel.so qnn_sdk_242/.../lib/hexagon-v79/unsigned/ Skel DSP (hexagon)
libQnnHtpPrepare.so qnn_sdk_242/.../lib/aarch64-android/ Préparation graphe HTP
libQnnSystem.so qnn_sdk_242/.../lib/aarch64-android/ Système QNN
libQnnModelDlc.so qnn_sdk_242/.../lib/aarch64-android/ Chargement modèles DLC
libQnnHtpNetRunExtensions.so qnn_sdk_242/.../lib/aarch64-android/ Extensions réseau HTP
hybrid_llama_qnn.pte models_qnn/qwen3-*-executorch/ Modèle ExecuTorch
tokenizer.json models_qnn/qwen3-*-executorch/ Tokenizer HuggingFace

IMPORTANT : Les libs Skel DOIVENT venir du même SDK que celui utilisé pour compiler le .pte. Ne PAS utiliser les libs vendor de la tablette (/vendor/lib64/hw/audio/).

Script de déploiement

#!/bin/bash
QNN="/opt/Kazeia/qnn_sdk_242/qairt/2.42.0.251225"
ET="/opt/Kazeia/executorch"
DIR="/data/local/tmp/kazeia-et"
MODEL_DIR="/opt/Kazeia/models_qnn/qwen3-0_6b-executorch"  # ou qwen3-1_7b-executorch

# Créer répertoire
adb shell "rm -rf $DIR && mkdir -p $DIR/outputs"

# Libs QNN SDK 2.42
adb push $QNN/lib/aarch64-android/libQnnHtp.so $DIR/
adb push $QNN/lib/aarch64-android/libQnnHtpV79Stub.so $DIR/
adb push $QNN/lib/hexagon-v79/unsigned/libQnnHtpV79Skel.so $DIR/
adb push $QNN/lib/aarch64-android/libQnnHtpPrepare.so $DIR/
adb push $QNN/lib/aarch64-android/libQnnSystem.so $DIR/
adb push $QNN/lib/aarch64-android/libQnnModelDlc.so $DIR/
adb push $QNN/lib/aarch64-android/libQnnHtpNetRunExtensions.so $DIR/

# ExecuTorch
adb push $ET/build-android/backends/qualcomm/libqnn_executorch_backend.so $DIR/
adb push $ET/build-android/examples/qualcomm/oss_scripts/llama/qnn_llama_runner $DIR/

# Modèle + Tokenizer
adb push $MODEL_DIR/hybrid_llama_qnn.pte $DIR/
adb push $MODEL_DIR/tokenizer.json $DIR/

# Permissions
adb shell "chmod +x $DIR/qnn_llama_runner"

Exécution

adb shell "su -c 'cd /data/local/tmp/kazeia-et && \
  export LD_LIBRARY_PATH=/data/local/tmp/kazeia-et && \
  export ADSP_LIBRARY_PATH=/data/local/tmp/kazeia-et && \
  ./qnn_llama_runner \
    --model_path hybrid_llama_qnn.pte \
    --tokenizer_path tokenizer.json \
    --decoder_model_version qwen3 \
    --output_path outputs/outputs.txt \
    --performance_output_path outputs/perf.txt \
    --shared_buffer \
    --prompt \"Votre prompt ici\" \
    --system_prompt \"Tu es Kazeia, compagnon écoute émotionnelle.\" \
    --temperature 0.7 \
    --seq_len 256 \
    --eval_mode 1'"

Paramètres clés

Paramètre Valeur Description
--decoder_model_version qwen3 Template de chat Qwen3
--eval_mode 1 Mode hybride (prefill + KV cache)
--shared_buffer (flag) OBLIGATOIRE — mémoire partagée CPU↔DSP
--output_path chemin Fichier de sortie texte
--temperature 0.0-1.0 0 = déterministe, 0.7 = créatif
--seq_len 128-4096 Longueur max (prompt + réponse)

Performances mesurées

Qwen3-0.6B (660 MB)

  • Chargement : 0.86s
  • Prefill : 31ms (451 tok/s)
  • Génération : 93.15 tok/s
  • Temps au premier token : 31ms
  • RAM : ~698 MB

Qwen3-1.7B (1.7 GB)

  • Génération : ~25.7 tok/s (benchmark mars 2026)

Mistral-Nemo 12B (7.4 GB)

  • Génération : ~5.1 tok/s (benchmark mars 2026)

Modèles disponibles

Modèle Fichier .pte Taille Qualité FR
Qwen3-0.6B qwen3-0_6b-executorch/hybrid_llama_qnn.pte 660 MB Basique
Qwen3-1.7B qwen3-1_7b-executorch/hybrid_llama_qnn.pte 1.7 GB Bonne
Mistral-Nemo 12B mistral-nemo-executorch/hybrid_llama_qnn.pte 7.4 GB Excellente

Erreurs courantes

loadRemoteSymbols failed with err 4000

  • Cause : Libs Skel manquantes ou incompatibles
  • Fix : Vérifier que libQnnHtpV79Skel.so vient du SDK 2.42 (hexagon-v79/unsigned/), pas du vendor

SoC model (SnapdragonModel) is unknown

  • Cause : Utilisation des libs vendor au lieu des libs SDK
  • Fix : Ne PAS utiliser /vendor/lib64/hw/audio/libQnn*.so

Runner se termine sans générer de texte

  • Cause : --shared_buffer et --output_path manquants
  • Fix : Ajouter les deux paramètres

Failed to create transport for device

  • Cause : libQnnModelDlc.so manquant
  • Fix : Copier depuis qnn_sdk_242/.../lib/aarch64-android/

Projet Kazeia — Damien Micottis & Richard Loyer