ExecuTorch
ExecuTorch führt PyTorch-Programme auf Edge-Zielen aus. LibreYOLO erfasst das Modell mit torch.export im Strict-Modus, überführt es per Lowering auf XNNPACK und legt das .pte-Programm zusammen mit einer JSON-Metadaten-Sidecar-Datei als eine Einheit ab.
- Flag
export(format="executorch")- Schreibt
- Ein .pte-Programm plus eine .pte.json-Metadaten-Sidecar-Datei
- Extra
pip install "libreyolo[executorch]"- Lädt zurück
LibreYOLO("weights/LibreYOLO9t.pte")- Shapes
- Fest. dynamic=True und batch != 1 werden abgelehnt.
- Präzision
- Nur FP32. half=True und int8=True werden abgelehnt.
- Delegate
- XNNPACK, CPU. delegate='xnnpack' ist der einzige akzeptierte Wert.
Installation
# Bewusst nicht in libreyolo[all]: ExecuTorch schränkt ein, mit welcher# Torch-Version es kombiniert werden kann.pip install "libreyolo[executorch]"Dieses Extra liegt bewusst außerhalb von libreyolo[all], weil ExecuTorch
festlegt, mit welcher Torch-Version es funktioniert, und eine Installation die
gesamte Umgebung auf diese Paarung ziehen würde. Installiere es in eine Umgebung,
die du bereit bist einzuschränken.
Unter Windows ruft der Lowering-Schritt die ausführbare Datei flatc auf, die
ExecuTorch mitliefert. Liegt sie nicht im PATH, löst der Export einen
RuntimeError mit genau diesem Hinweis aus, und der Ausweg ist, aus einer
Developer PowerShell von Visual Studio 2022 heraus zu starten.
Export
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Schreibt weights/LibreYOLO9t.pte und weights/LibreYOLO9t.pte.jsonpath = model.export(format="executorch", imgsz=640)print(path)libreyolo export --model LibreYOLO9t.pt --format executorch --imgsz 640model.export( format="executorch", imgsz=640, # int, oder (Höhe, Breite) batch=1, # jeder andere Wert löst ValueError aus dynamic=False, # True löst ValueError aus delegate="xnnpack", # der einzige akzeptierte Wert device="cpu", # jedes andere Gerät löst ValueError aus output_path=None, # None schreibt weights/<stem>.pte)Erfasst wird mit torch.export.export(..., strict=True), also eine echte
Graph-Erfassung mit Guards statt eines aufgezeichneten Trace. Lesezugriffe auf
Host-Skalare und datenabhängiger Kontrollfluss werden abgelehnt, statt still
eingebacken zu werden, deshalb scheitern hier mehrere Familien, deren Tracing
anderswo gelingt; die Gründe stehen pro Kombination in der Support-Matrix.
Das Lowering führt to_edge_transform_and_lower mit dem XNNPACK-Partitioner aus.
Enthält das Ergebnis null Delegate-Partitionen, bricht der Export mit einem Fehler
ab, statt ein Programm aus reinen Portable-Kernels als XNNPACK auszuweisen.
Programm und Sidecar-Datei werden gemeinsam festgeschrieben. Beide werden vorab abgelegt, beide werden eingewechselt, und ein Fehler setzt auf den vorherigen Stand zurück, ein halbes Paar landet also nie auf der Festplatte.
Ausführen des Artefakts
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t.pte")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])import jsonfrom pathlib import Path import torchfrom executorch.runtime import Runtime runtime = Runtime.get()print(runtime.backend_registry.is_available("XnnpackBackend")) program = runtime.load_program(Path("weights/LibreYOLO9t.pte").read_bytes())method = program.load_method("forward") # Pre- und Postprocessing liegen auf diesem Weg bei dir.outputs = method.execute((torch.zeros(1, 3, 640, 640),))print([tensor.shape for tensor in outputs]) meta = json.load(open("weights/LibreYOLO9t.pte.json"))print(meta["model_family"], meta["task"], meta["executorch_delegate"])LibreYOLO() entscheidet anhand der Endung .pte und liefert dasselbe
Results-Objekt wie der Checkpoint. Die Sidecar-Datei ist beim Laden Pflicht:
ohne <program>.pte.json löst das Backend einen FileNotFoundError aus, weil das
Programm selbst keine Klassennamen, keine Aufgabe und keine Eingabegröße
mitbringt. Das Backend prüft vor dem Laden außerdem, ob die installierte Runtime
XnnpackBackend bereitstellt, und liest das Programm aus Bytes, statt die Datei zu
mappen, was verhindert, dass unter Windows für die Lebensdauer des Backends eine
Dateisperre gehalten wird.
Das zweite Snippet ist der Weg über die reine Runtime. Preprocessing, Decoding, NMS und die Skalierung der Koordinaten liegen dort bei dir.
Einschränkungen
Batch 1, feste Shape, FP32, CPU. batch != 1 und dynamic=True lösen beide einen
ValueError aus, bevor der Export irgendetwas verändert, half=True und
int8=True werden bei der Validierung abgelehnt, und ein anderes Gerät als die CPU
wird verweigert.
delegate akzeptiert in dieser Version "xnnpack" und sonst nichts.
Exporte für die Klassifikation tragen zwei zusätzliche Metadaten-Schlüssel,
crop_pct und interpolation, damit die Runtime das Resize- und
Center-Crop-Verhalten der Familie reproduzieren kann.
Die blockierten Einträge benennen den konkreten Fehler statt einer Kategorie.
D-FINE-Erkennung und -Segmentierung stoßen unter der strikten Erfassung auf einen
nicht unterstützten ContextVar-Lesezugriff in der Deformable Attention, und der
erzwungene manuelle Grid-Sample-Weg serialisiert zwar, scheitert dann aber zur
Laufzeit an einer ungültigen Dimensionsreihenfolge des delegierten Tensors. DEIM
und DEIMv2 durchlaufen Erfassung, Lowering und Serialisierung und scheitern dann
während der Ausführung. Die semantische Segmentierung von EoMT scheitert an einem
datenabhängigen symbolischen Ausdruck im Masken-Pfad. BiRefNet-Matting wird bei
1024 mal 1024 erfasst, hat aber keine Out-Variante für
torchvision::deform_conv2d. Die SwinIR-Restaurierung lädt zwar wieder, scheitert
dann aber in aten::alias_copy.out an nicht zusammenpassenden
Dimensionsreihenfolgen.
Das vollständige Raster aus Familien und Aufgaben steht in der Export-Matrix. Für eine einzelne Kombination:
libreyolo formats --family yolo9 --task detect