Skip to content

v0.3.0 — surgical FP16 + export sliders

Choose a tag to compare

@PogChamper PogChamper released this 03 Jul 16:53

D-FINE-cpp v0.3.0

Surgical FP16 and export-time speed sliders. The production ONNX moves from "FP16 with the decoder
kept FP32" to whole-net FP16 with a minimal FP32 island — lossless full-val mAP on all five
sizes at +6…19% batch-8 throughput — and the export script gains sliders that trade fractions of
an AP point for up to +46% over the v0.2.0 tier. No ABI change; v0.2.0 binaries and engines keep
working.

Surgical FP16 (convert_fp16_surgical.py, new production default)

The decoder is ~46% of GPU time and was FP32 until now — not because it all needs the precision,
but because naive decoder FP16 collapses mAP. The surgical converter runs the whole net FP16,
including the deformable-attention data path, and pins only what measurably needs FP32: the FDR
scopes (Integral/LQE/bbox heads) and the deform coordinate/index math (FP16 integers above 2048
are inexact — wrong-pixel gathers). --slim (the release default) is the tightest gated island.

  • Lossless, full COCO val, all five sizes--slim: n 0.4272, s 0.5060, m 0.5500 (== the
    fp16_st reference exactly), l 0.5723, x 0.5926; non-slim surgical: n 0.4276, s 0.5065,
    m 0.5502, l 0.5724, x 0.5929.
  • Batch-8 (surgical tier, conservative — slim benched +2-3% on top where measured): n 1234→1309,
    s 637→758, m 469→526 (561 with --opt-batch 8), l 357→390, x 244→264 img/s;
    VRAM −28…−124 MiB; zero plugins.
  • Requires an opset-19 export and hard-errors below it: opset-16 exports decompose LayerNorm
    and TensorRT 10.13 miscompiles the decomposition in FP16 (mAP → ~0.005 while ONNXRuntime stays
    healthy; minimal repro archived, NVIDIA report in preparation).
  • The full-pipeline CUDA graph runs on a --max-aux-streams 0 surgical engine unchanged:
    byte-identical detections, 2.474 ms end-to-end batch-1 — the repo's latency record.

Export sliders (export_dfine_onnx.py)

Three decoder reshapes applied before deploy()/tracing, so the graph itself shrinks
(m, full-val, b8, gains vs the surgical b8 median): --num-queries 200 = −0.13 AP / +7%;
--cascade K:KEEP = keep the top-KEEP queries after layer K ranked by that layer's trained
deep-supervision head (1:150 = −0.18 AP / +8%, the best single slider); --eval-idx 2 =
−0.57 AP / +4%. Composed presets: fast
(Q200 + cascade 1:100) = +11…19% over surgical across the lineup at −0.44…−0.77 AP; max (fast +
eval-idx 2 + --opt-batch 8) = 686 img/s on m, 10.4× PyTorch, −0.89 AP. Every measured point, including
the paths that closed negative (FP8, INT8, deform plugin), is in
docs/RESEARCH_MATRIX.md.

Python: engine builds without a repo checkout

The wheel now bundles a snapshot of build_engine.py (self-contained: tensorrt + stdlib), so the
release quickstart is wheel + two curls + one dfine build — verified end-to-end in a fresh venv.
dfine build gains --opt-batch; --onnx without --model now derives the cache name from the
ONNX stem instead of producing a dfine_None engine; fp16/fp32 ONNX resolution understands the
new _slim/_op19 release names. New notebook:
examples/python_quickstart.ipynb.

Validation

WERROR=ON build clean; C-ABI byte-parity PASS (fp32 + fp16_st); 14/14 pytests; the default
export path is byte-identical with the new flags unset (same-session A/B of the ONNX and
sidecar). The flag-based exports reproduce the research artifacts that passed the full-val gates
bit-exactly (graph node/initializer hashes match for the fast preset and for all five slim
release assets), so the shipped flags inherit those gates directly. Slider engines were
additionally gated: cascade 1:150 full-val 0.5482 (−0.18), fast preset full-val on all five sizes.

Artifacts

dfine_{n,s,m,l,x}_op19.onnx (FP32 opset-19 base) + dfine_{n,s,m,l,x}_slim.onnx (surgical-FP16
production) + .json sidecars + SHA256SUMS + dfine-0.3.0-py3-none-linux_x86_64.whl (sm_89;
needs local TensorRT 10.x + CUDA 12) + demo mp4s. The v0.2.0 fp16_st/fp32 op16 assets remain
valid and stay on the v0.2.0 release.