Commit 76dbfda2 authored by Andrey Filippov's avatar Andrey Filippov

CLAUDE: add export_torchscript.py — TorchScript export for native LibTorch inference

Validated in PoC: L1 (weighted9_pm_s) -> TorchScript -> C++/CUDA on Blackwell matches PyTorch (7.6e-4).
Writes raw-f32 reference vectors for the native probe.
Co-Authored-By: 's avatarClaude Opus 4.8 (1M context) <noreply@anthropic.com>
parent 782ef529
Pipeline #3824 canceled with stages
# export_torchscript.py - part of imagej_elphel_dnn (Elphel DNN: tile-processor motion detection / ranging)
#
# Copyright (C) 2026 Elphel, Inc.
#
# -----------------------------------------------------------------------------
# imagej_elphel_dnn is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# -----------------------------------------------------------------------------
"""Export a trained L1 (RawFCN) model.pt checkpoint to self-contained TorchScript for native
LibTorch inference (no Python at runtime). Build-once on a dev box with the *matching* torch
version (e.g. torch==2.7.1 to match libtorch 2.7.1+cu128).
Usage: python export_torchscript.py runs/weighted9_pm_s/model.pt [out.ts.pt]
Also writes <out>.test_input.bin / <out>.test_output.bin (raw little-endian f32) reference
vectors for the C++ probe to verify the native output against PyTorch. By Claude on 06/27/2026.
"""
import sys, struct, torch
from model import RawFCN
ckpt = sys.argv[1]
out = sys.argv[2] if len(sys.argv) > 2 else (ckpt[:-3] if ckpt.endswith(".pt") else ckpt) + ".ts.pt"
ck = torch.load(ckpt, map_location="cpu", weights_only=False)
a = ck.get("args", {}) or {}
kw = dict(n_frames=a.get("nframes", 8), vel_radius=a.get("vel_radius", 5),
patch=a.get("patch", 24), velocity_mode=a.get("velocity_mode", "grid"), vmax=a.get("vmax", 1.4))
if a.get("ch") is not None:
kw["ch"] = tuple(a["ch"])
m = RawFCN(**kw); m.load_state_dict(ck["model"]); m.eval()
print("config:", kw, "out_ch", m.out_ch)
torch.manual_seed(0)
N, P = kw["n_frames"], kw["patch"]
x = torch.randn(1, N, P, P)
with torch.no_grad():
y = m(x)
ts = torch.jit.script(m); ts.save(out)
ts2 = torch.jit.load(out, map_location="cpu"); ts2.eval()
with torch.no_grad():
d = (ts2(x) - y).abs().max().item()
print(f"saved {out}; reload max|diff| vs eager = {d}")
def _w(path, t):
f = t.contiguous().view(-1).tolist()
open(path, "wb").write(struct.pack("<%df" % len(f), *f))
_w(out + ".test_input.bin", x)
_w(out + ".test_output.bin", y)
print(f"wrote reference vectors: {out}.test_input.bin {tuple(x.shape)}, {out}.test_output.bin {tuple(y.shape)}")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment