ExecuTorch
O ExecuTorch roda programas do PyTorch em alvos de borda (edge). O LibreYOLO captura o modelo com torch.export em modo estrito, faz o lowering para XNNPACK e grava o programa .pte junto com um sidecar de metadados JSON como uma unidade só.
- Flag
export(format="executorch")- Escreve
- Um programa .pte mais um sidecar de metadados .pte.json
- Extra
pip install "libreyolo[executorch]"- Recarrega com
LibreYOLO("weights/LibreYOLO9t.pte")- Formas
- Fixas. dynamic=True e batch != 1 são recusados.
- Precisão
- Somente FP32. half=True e int8=True são recusados.
- Delegado
- XNNPACK, CPU. delegate='xnnpack' é o único valor aceito.
Instalação
# Fora de libreyolo[all] de propósito: o ExecuTorch restringe com qual# versão do Torch ele pode ser combinado.pip install "libreyolo[executorch]"Este extra fica de propósito fora de libreyolo[all], porque o ExecuTorch fixa com
qual versão do Torch ele funciona e instalá-lo arrastaria o ambiente inteiro para
esse par. Instale esse extra em um ambiente que você esteja disposto a restringir.
No Windows, a etapa de lowering chama o executável flatc que vem junto com o
ExecuTorch. Se ele não estiver no PATH, a exportação levanta um RuntimeError
dizendo isso, e a solução é rodar a partir de um Developer PowerShell do Visual Studio 2022.
Exportação
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Escreve 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, ou (altura, largura) batch=1, # qualquer outro valor levanta ValueError dynamic=False, # True levanta ValueError delegate="xnnpack", # o único valor aceito device="cpu", # qualquer outro device levanta ValueError output_path=None, # None escreve weights/<stem>.pte)A captura é torch.export.export(..., strict=True), que é uma captura de grafo de
verdade, com guards, e não um trace gravado. Leituras de escalares no host e controle
de fluxo dependente de dados são recusados em vez de ficarem embutidos em silêncio,
então várias famílias falham aqui apesar de traçarem sem problema em outros formatos;
os motivos ficam registrados por combinação na matriz de suporte.
O lowering roda to_edge_transform_and_lower com o partitioner do XNNPACK. Se o
resultado não tiver nenhuma partição delegada, a exportação levanta um erro em vez de
rotular como XNNPACK um programa que só usa kernels portáteis.
O programa e o sidecar são gravados juntos. Os dois passam pela área de staging, os dois são trocados de uma vez, e uma falha reverte para o que estava lá antes, de modo que um par incompleto nunca chega ao disco.
Rodar o artefato
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") # O pré-processamento e o pós-processamento ficam por sua conta neste caminho.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() despacha pelo sufixo .pte e devolve o mesmo objeto Results que o
checkpoint. O sidecar é obrigatório no carregamento: sem <program>.pte.json o backend
levanta FileNotFoundError, porque o programa não carrega nomes de classes, tarefa nem
tamanho de entrada próprios. O backend também confere se o runtime instalado fornece
XnnpackBackend antes de carregar, e lê o programa a partir de bytes em vez de mapear o
arquivo, o que evita segurar um lock de arquivo do Windows por toda a vida do backend.
O segundo snippet é o caminho do runtime puro. O pré-processamento, a decodificação, o NMS e o reescalonamento de coordenadas ficam por sua conta ali.
Restrições
Batch 1, forma fixa, FP32, CPU. batch != 1 e dynamic=True levantam ValueError
antes que a exportação altere qualquer coisa, half=True e int8=True são recusados
durante a validação, e um device diferente de CPU é rejeitado.
delegate aceita "xnnpack" e nada mais nesta versão.
As exportações de classificação carregam duas chaves extras de metadados, crop_pct e
interpolation, para que o runtime consiga reproduzir a política de resize e center-crop
da família.
As entradas bloqueadas nomeiam a falha concreta em vez de uma categoria. A detecção e a
segmentação com D-FINE esbarram em uma leitura de ContextVar não suportada na deformable
attention sob captura estrita, e forçar o caminho manual de grid-sample serializa, mas
depois falha em tempo de execução por uma ordem de dimensões inválida no tensor delegado.
DEIM e DEIMv2 capturam, fazem o lowering e serializam, e então falham durante a execução.
A segmentação semântica com EoMT falha em uma expressão simbólica dependente de dados no
caminho da máscara. O matting com BiRefNet captura em 1024 por 1024, mas não tem variante
out para torchvision::deform_conv2d. A restauração com SwinIR recarrega e então falha em
aten::alias_copy.out por ordens de dimensões incompatíveis.
Para a grade completa de famílias e tarefas, veja a matriz de exportação. Para uma combinação:
libreyolo formats --family yolo9 --task detect