Hailo
Gli acceleratori Hailo si compilano con l'Hailo Dataflow Compiler, un SDK proprietario distribuito attraverso la Developer Zone di Hailo. La parte del flusso che spetta a LibreYOLO è una semplice esportazione ONNX statica; il parsing, la quantizzazione e la compilazione in un HEF avvengono dopo, dentro il DFC.
- Passo LibreYOLO
export(format="onnx", imgsz=640, dynamic=False)- Non è un formato
- Non esiste format="hef". Il DFC non può essere una dipendenza pip.
- Extra
pip install "libreyolo[onnx]"- Host di compilazione
- Linux x86_64, inclusa WSL2 Ubuntu 22.04. La compilazione non può girare su ARM.
- Cosa si compila
- Grafi puramente CNN, a forma fissa. L'attenzione, le forme dinamiche e i design dominati da LayerNorm no.
- Stato
- Nessuna famiglia LibreYOLO è ancora stata portata da un capo all'altro del DFC fino a un HEF funzionante.
Installazione
In LibreYOLO non esiste format="hef" e non esisterà. L'Hailo Dataflow Compiler
è un SDK proprietario distribuito come wheel privata dietro la registrazione alla
Developer Zone, quindi non può essere una dipendenza né un extra. Il deployment
ha due fasi: LibreYOLO scrive un file ONNX statico, e sei tu a passarci sopra il
DFC.
Libre<Model>.pt -> ONNX -> HAR (parse) -> HAR (quantize INT8) -> HEF
[libreyolo] [Hailo DFC, installed by you]pip install "libreyolo[onnx]"Prerequisites, none of them installable from PyPI: - A Linux x86_64 machine. WSL2 Ubuntu 22.04 works. The Raspberry Pi is a runtime target, never the compile host.- The Dataflow Compiler wheel (hailo_sdk_client) from the Hailo Developer Zone, which is free to register for.- For Hailo-8 and Hailo-8L, the Hailo Model Zoo v2.x line, for its recipes and NMS configurations.- A GPU on the compile host is strongly recommended: the quantization step takes hours without one.Esportazione
from libreyolo import LibreYOLO # Hailo richiede batch 1, una risoluzione fissa e nessun asse dinamico.# L'API Python usa dynamic=True di default, quindi disattivalo esplicitamente.model = LibreYOLO("LibreYOLOXs.pt")model.export(format="onnx", imgsz=640, dynamic=False, simplify=True)# La CLI usa già forme statiche di default.libreyolo export --model LibreYOLOXs.pt --format onnx --imgsz 640import onnx graph = onnx.load("weights/LibreYOLOXs.onnx").graphshape = graph.input[0].type.tensor_type.shapeprint([d.dim_value or d.dim_param for d in shape.dim])Non passare half=True. Il DFC prende in ingresso ONNX FP32 e fa la propria
quantizzazione INT8. Non passare nemmeno nms=True: o la NMS è in carico a Hailo
tramite nms_postprocess, o è in carico all'applicazione, e un sottografo di NMS
è peso morto oltre i nodi finali. L'opset predefinito funziona; se il parser del
DFC protesta, riesporta con opset=11.
Il DFC taglia il grafo ai nodi finali che indichi, cioè le convoluzioni della testa di rilevamento, e scarta tutto quello che sta a valle. L'ONNX decodificato ordinario di LibreYOLO è quindi un input accettabile: la coda di decodifica viene semplicemente ignorata dal parser.
Compilazione
from pathlib import Path import numpy as npfrom hailo_sdk_client import ClientRunnerfrom PIL import Image ONNX = "weights/LibreYOLOXs.onnx"HW_ARCH = "hailo8" # hailo8 | hailo8l | hailo10hIMGSZ = 640 runner = ClientRunner(hw_arch=HW_ARCH) # Per YOLOX, esegui la traduzione una volta senza end_node_names: il log# del DFC stampa i nodi finali che suggerisce. Rilancia con quelli.runner.translate_onnx_model(ONNX) # La normalizzazione deve corrispondere al preprocessing di LibreYOLO.# YOLOX e YOLO9 non richiedono media né deviazione standard, solo la# scala da 0-255 a 0-1.script = "normalization1 = normalization([0.0, 0.0, 0.0], [255.0, 255.0, 255.0])\n" # Facoltativo: lascia la NMS a Hailo. La configurazione è specifica sia# del numero di classi sia della dimensione di input, quindi una# configurazione COCO-80 è sbagliata per un modello a tre classi# affinato con fine-tuning. Senza questa riga l'HEF emette i tensori# grezzi della testa e li decodifica l'applicazione.# script += 'nms_postprocess("yolox_nms_config.json", meta_arch=yolox, engine=cpu)\n' runner.load_model_script(script) # Le immagini di calibrazione devono essere rappresentative dei dati di# produzione. Immagini casuali si compilano e distruggono in silenzio# l'accuratezza.calib_paths = sorted(Path("calib_images").glob("*.jpg"))[:128]calib = np.stack([ np.asarray( Image.open(p).convert("RGB").resize((IMGSZ, IMGSZ)), dtype=np.float32, ) for p in calib_paths]) runner.optimize(calib)Path("libreyoloxs.hef").write_bytes(runner.compile())# I grafi LibreYOLO usano un prefisso "/head/...", non il prefisso# "model.N" che si vede nelle configurazioni scritte per altre# esportazioni. Una configurazione copiata non corrisponde. Se il# parsing fallisce, verifica i nomi nel tuo grafo.END_NODES = [ "/head/cv2.0/cv2.0.2/Conv", "/head/cv3.0/cv3.0.2/Conv", "/head/cv2.1/cv2.1.2/Conv", "/head/cv3.1/cv3.1.2/Conv", "/head/cv2.2/cv2.2.2/Conv", "/head/cv3.2/cv3.2.2/Conv",]runner.translate_onnx_model(ONNX, end_node_names=END_NODES)Scegli hw_arch in base al target: hailo8 per Hailo-8, l'AI HAT+ da 26 TOPS e
i moduli M.2 e PCIe; hailo8l per Hailo-8L, il Raspberry Pi AI Kit e l'AI HAT+
da 13 TOPS; hailo10h per Hailo-10H, che richiede un DFC e un Model Zoo più
recenti e corrispondenti. Se hai dubbi, hailortcli fw-control identify sul
dispositivo risponde alla domanda.
Due famiglie corrispondono a una meta-architettura NMS di HailoRT, quindi la
soppressione può stare in carico a Hailo dentro la pipeline compilata: YOLOX
tramite meta_arch=yolox, e YOLO9 tramite la meta-architettura a testa
disaccoppiata di Hailo, la cui disposizione della testa è identica. Prendi la
configurazione nms_postprocess corrispondente dal Model Zoo di Hailo e adattala
al tuo numero di classi e alla tua dimensione di input. Ogni altro rilevatore
convoluzionale si compila come un grafo senza meta-architettura corrispondente:
l'HEF emette i tensori grezzi della testa e l'applicazione esegue decodifica e
NMS sulla CPU.
Conserva il log di compilazione quando qualcosa fallisce. Ogni correzione dipende dal nome esatto del layer o dell'operatore che fallisce.
Eseguire l'artefatto
sudo apt install dkms hailo-allhailortcli fw-control identify # controllo del dispositivo, e dice qual è l'architetturahailortcli run libreyoloxs.hef # smoke test e throughputL'inferenza dell'applicazione usa l'API Python hailo_platform. Con
nms_postprocess compilato dentro, l'output è (batch, num_classes, max_dets, 5)
e contiene [y1, x1, y2, x2, score] in coordinate del modello, che riporti in
scala sull'immagine di origine tu stesso. La pipeline Results di LibreYOLO non
entra in gioco a runtime; l'HEF è un artefatto autonomo, e il preprocessing e il
postprocessing sono dell'applicazione.
Vincoli
Che un modello possa avere come target Hailo-8 o Hailo-8L è una proprietà della sua architettura, non del suo nome, quindi la regola qui sotto vale anche per le famiglie aggiunte dopo che questa pagina è stata scritta.
Un modello non si compila se contiene una qualsiasi di queste cose:
- Attenzione di qualunque tipo: self, cross, deformabile o a finestre. Questo esclude ogni rilevatore in stile DETR, ogni rilevatore a vocabolario aperto o condizionato dal testo, ogni backbone ViT e ogni torre linguistica o vision-language. Lo zoo di Hailo distribuisce qualche HEF transformer messo a punto a mano; è lavoro su misura del fornitore e non è la prova che un grafo con attenzione qualsiasi si compili.
- Forme dinamiche o flusso di controllo che dipende dai dati. Il DFC compila una
sola forma di input fissa e un grafo statico, quindi numeri di query variabili,
prompt testuali, top-k dinamico,
NonZero,GatheroTopKcon indici dinamici egrid_samplesono tutti esclusi. - Un design dominato da LayerNorm o da GELU. La BatchNorm si fonde con le convoluzioni in modo pulito; il supporto per LayerNorm è scarso e GELU non è un'attivazione nativa, quindi uno stack in stile ConvNeXt non è adatto anche se è nominalmente convoluzionale.
- Lavoro image-to-image a risoluzione nativa. I modelli di restauro girano alla risoluzione piena dell'input e superano i budget pratici di SRAM di Hailo.
Una famiglia è candidata quando è di sole convoluzioni, usa BatchNorm con ReLU o SiLU e ha una dimensione di input fissa. In questa libreria vuol dire i rilevatori CNN a stadio singolo, con YOLOX e YOLO9 come target principali; gli altri rilevatori convoluzionali come PicoDet, YOLO-NAS e RTMDet, con la decodifica lato applicazione; i classificatori CNN ResNet, MobileNetV4-conv ed EfficientNetV2, di cui ResNet è il meglio supportato perché il Model Zoo di Hailo distribuisce ricette per esso; e le piccole teste di task convoluzionali come il rilevamento a punti FOMO e lo sguardo L2CS su un backbone ResNet, compilabili in linea di principio ma senza una ricetta Hailo.
Un avvertimento sullo stato, che è il motivo per cui nulla in questa pagina viene presentato come supportato: nessuna famiglia LibreYOLO è stata portata da un capo all'altro del DFC fino a un HEF funzionante. Le regole qui sopra prevedono la compilabilità a partire dall'architettura. Il comportamento del parser, la quantizzazione e l'accuratezza restano non dimostrati finché un HEF non viene compilato e misurato, quindi considera che ogni candidato richieda le proprie prove registrate: un HEF compilato a partire dal checkpoint esatto, con le versioni di DFC, Model Zoo e HailoRT annotate, una calibrazione documentata e un confronto di accuratezza sul dispositivo rispetto alla baseline FP32, non un numero di throughput.
Se il modello è escluso, le alternative sono i runtime con parità registrata: ONNX, TensorRT e OpenVINO.