ExecuTorch
ExecuTorch esegue programmi PyTorch su dispositivi edge. LibreYOLO cattura il modello con torch.export in modalità strict, fa il lowering su XNNPACK e scrive il programma .pte insieme a un sidecar di metadati JSON come una cosa sola.
- Flag
export(format="executorch")- Scrive
- Un programma .pte più un sidecar di metadati .pte.json
- Extra
pip install "libreyolo[executorch]"- Si ricarica con
LibreYOLO("weights/LibreYOLO9t.pte")- Forme
- Fisse. dynamic=True e batch != 1 vengono rifiutati.
- Precisione
- Solo FP32. half=True e int8=True vengono rifiutati.
- Delegato
- XNNPACK, CPU. delegate='xnnpack' è l'unico valore accettato.
Installazione
# Escluso da libreyolo[all] di proposito: ExecuTorch limita con quale# versione di Torch può essere abbinato.pip install "libreyolo[executorch]"Questo extra sta deliberatamente fuori da libreyolo[all], perché ExecuTorch fissa
con quale versione di Torch funziona e installarlo trascinerebbe l'intero ambiente
su quella coppia. Installalo in un ambiente che sei disposto a vincolare.
Su Windows il passo di lowering chiama l'eseguibile flatc distribuito con
ExecuTorch. Se non è nel PATH, l'esportazione solleva un RuntimeError che lo
segnala, e la soluzione è eseguirla da una Developer PowerShell di Visual Studio 2022.
Esportazione
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Scrive weights/LibreYOLO9t.pte e 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, oppure (altezza, larghezza) batch=1, # qualsiasi altro valore solleva ValueError dynamic=False, # True solleva ValueError delegate="xnnpack", # l'unico valore accettato device="cpu", # qualsiasi altro dispositivo solleva ValueError output_path=None, # None scrive weights/<stem>.pte)La cattura è torch.export.export(..., strict=True), cioè una vera cattura del
grafo con guard invece di un trace registrato. Le letture di scalari sull'host e il
controllo di flusso dipendente dai dati vengono rifiutati invece di essere fissati
in silenzio, quindi qui falliscono diverse famiglie che altrove si tracciano senza
problemi; i motivi sono registrati per combinazione nella matrice di supporto.
Il lowering esegue to_edge_transform_and_lower con il partitioner XNNPACK. Se il
risultato non contiene nessuna partizione delegata, l'esportazione solleva un errore
invece di etichettare come XNNPACK un programma che usa solo kernel portabili.
Il programma e il sidecar vengono scritti insieme. Entrambi vengono preparati, entrambi vengono sostituiti, e un errore riporta tutto a com'era prima, così una coppia incompleta non arriva mai sul disco.
Eseguire l'artefatto
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") # Su questa via il preprocessing e il postprocessing sono affare tuo.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() sceglie in base al suffisso .pte e restituisce lo stesso oggetto
Results del checkpoint. Il sidecar è obbligatorio al caricamento: senza
<program>.pte.json il backend solleva FileNotFoundError, perché il programma non
porta con sé nomi di classe, task né dimensione di input. Il backend controlla anche
che il runtime installato offra XnnpackBackend prima di caricare, e legge il
programma dai byte invece di mappare il file, il che evita di tenere un lock di file
di Windows per tutta la vita del backend.
Il secondo snippet è la via del runtime diretto. Lì il preprocessing, la decodifica, l'NMS e il riscalamento delle coordinate diventano affare tuo.
Vincoli
Batch 1, forma fissa, FP32, CPU. Sia batch != 1 sia dynamic=True sollevano
ValueError prima che l'esportazione modifichi qualcosa, half=True e int8=True
vengono rifiutati durante la validazione, e un dispositivo diverso dalla CPU viene
respinto.
delegate accetta "xnnpack" e nient'altro in questa versione.
Le esportazioni di classificazione portano due chiavi di metadati extra, crop_pct e
interpolation, così il runtime può riprodurre la politica di ridimensionamento e
ritaglio centrale della famiglia.
Le voci bloccate indicano il fallimento concreto invece di una categoria. Il
rilevamento e la segmentazione di D-FINE arrivano a una lettura di ContextVar non
supportata nell'attenzione deformabile sotto cattura strict, e forzare la via manuale
del grid-sample serializza ma poi fallisce a runtime per un ordine di dimensioni non
valido su un tensore delegato. DEIM e DEIMv2 vengono catturati, passano il lowering e
si serializzano, poi falliscono durante l'esecuzione. La segmentazione semantica di
EoMT fallisce su un'espressione simbolica dipendente dai dati nel percorso delle
maschere. Il matting di BiRefNet viene catturato a 1024 per 1024 ma non ha una
variante out per torchvision::deform_conv2d. Il restauro di SwinIR si ricarica e poi
fallisce in aten::alias_copy.out per ordini di dimensioni non corrispondenti.
Per la griglia completa di famiglie e task, vedi la matrice di esportazione. Per una singola combinazione:
libreyolo formats --family yolo9 --task detect