torch#

This page answers common “how do I…” questions for converting torch models to ONNX with yobx.torch.interpreter.to_onnx().


How to choose how the FX graph is produced#

ExportOptions exposes three practical ways to obtain the FX graph before ONNX conversion.

1) torch.export.export path (default)

Use strategy="nostrict" (default) or strategy="strict":

from yobx.torch.export_options import ExportOptions
from yobx.torch.interpreter import to_onnx

artifact = to_onnx(model, (x,), export_options=ExportOptions(strategy="nostrict"))

2) Symbolic FX tracing (CustomTracer)

Use strategy="tracing":

artifact = to_onnx(model, (x,), export_options=ExportOptions(strategy="tracing"))

3) Dispatch-based tracing (new-tracing)

Use strategy="new-tracing":

artifact = to_onnx(model, (x,), export_options=ExportOptions(strategy="new-tracing"))

Quick summary#

The table below summarizes not only capture/backend routing, but also how decomposition is handled and when each option is usually the most practical.

Option

FX graph capture

ONNX conversion backend

Decomposition behavior

Typical use

strategy="nostrict" / "strict"

torch.export.export()

yobx converter

no explicit decomposition table by default; may still decompose only if inplace nodes cannot be removed directly

preferred default when you want yobx ATen-level conversion coverage

strategy="tracing"

symbolic CustomTracer

yobx converter

no explicit decomposition table by default; tracing normalizes many inplace patterns up front

useful when torch.export.export fails on a model but FX tracing works

strategy="new-tracing"

dispatch-based tracing

yobx converter

no explicit decomposition table by default; relies on new-tracing rewrites/patches for operator coverage

useful for models/operators better captured through dispatch-level tracing

strategy="onnxscript"

handled by torch.onnx.export()

official exporter

decomposition behavior follows the official exporter pipeline

use when you want direct parity with torch.onnx.export()


How to trigger the official exporter#

The official exporter path is torch.onnx.export(). You can trigger it through ExportOptions:

from yobx.torch.export_options import ExportOptions
from yobx.torch.interpreter import to_onnx

# direct torch.onnx.export(..., dynamo=True)
artifact = to_onnx(model, (x,), export_options=ExportOptions(strategy="onnxscript"))

How to read export and optimization statistics#

The returned ExportArtifact carries an ExportReport in artifact.report.

<<<

import torch
from yobx.torch.interpreter import to_onnx

model = torch.nn.Sequential(
    torch.nn.Linear(4, 8),
    torch.nn.ReLU(),
    torch.nn.Linear(8, 2),
).eval()
x = torch.randn(3, 4)

artifact = to_onnx(model, (x,), return_optimize_report=True)
print(artifact.report)
print(artifact.report.stats[:2])  # per-pattern optimization rows
print(artifact.report.extra.keys())  # timings, selected export options, counters

artifact.compute_node_stats()
print(artifact.report.node_stats[:2])  # per-op-type counts and estimated FLOPs

>>>

    ExportReport(n_stats=669, extra=['builder', 'optimization', 'stat_time_export_and_post_processing', 'stat_time_post_process_exported_program', 'stat_time_torch_export_export_oblivious', 'time_export_builder_process', 'time_export_graph_module', 'time_export_to_onnx'], has_build_stats=False, n_node_stats=0, n_symbolic_flops=0, n_discrepancies=0)
    [{'pattern': 'dynamic_dimension_naming', 'removed': 0, 'added': 0, 'time_in': 2.6520000005803013e-05}, {'pattern': 'check_A-dynamic_dimension_naming', 'time_in': 2.476700001352583e-05}]
    dict_keys(['builder', 'time_export_graph_module', 'stat_time_export_and_post_processing', 'stat_time_post_process_exported_program', 'stat_time_torch_export_export_oblivious', 'time_export_builder_process', 'optimization', 'time_export_to_onnx'])
    [{'op_type': 'Gemm', 'count': 2, 'flops': 318}, {'op_type': 'Relu', 'count': 1, 'flops': 24}]

The extra dictionary typically includes timing keys such as time_export_graph_module and flags describing which export options won the strategy fallback (for example onnx_export_options_strict or onnx_export_options_decomp).

If filename="model.onnx" is passed, the converter also writes model.xlsx with sheets such as extra, stats, stats_agg, node_stats, and symbolic_flops.


How this differs from torch.onnx.export#

By default, yobx.torch.interpreter.to_onnx() does not apply an explicit decomposition table, so ATen operators stay close to the original graph and are translated directly by yobx converters. A decomposition pass may still run if needed to eliminate inplace operations that could not be removed directly.