Repository navigation
Conversation
Warp APIC (1.18+) records a Torch-backed array as its entire storage allocation, so a segment reading wp.from_torch(traced[5:10]) binds the whole buffer while LEAPP fed the runner only the five-element view. The export then failed validation with "APIC param byte size mismatch". A traced view now remembers the traced tensor covering its storage, plus both proxies at the time the view was taken. A segment input over part of a Torch storage is replaced by that tensor, so every view of one buffer becomes a single runner input. If either side was modified in place since, or no traced tensor covers the storage, tracing fails with an explanation instead of exporting a stale buffer. Older Warp versions record the view as its own region, so they are rejected explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Lionel Gulich <lgulich@nvidia.com>
A node that resets a persistent buffer with buffer.zero_() or fill_() before accumulating into it exported a graph that never ran the reset: automatic segments only open at the first Warp call touching traced data, so the reset executed once during tracing and the runner then accumulated across calls. LEAPP's single-example validation could not see the drift. Everything between a node's input_tensors and output_tensors belongs to that node. An overwrite of an untraced array there now opens (or joins) that node's segment, and the array joins the node with its value bound to the runner output. Later readers, including segments split off by intervening Torch work, then depend on the runner through a graph edge. Only overwrites are attributed. A kernel launch on an untraced array may read its previous contents, which is undeclared state and stays a user error. When several nodes are open the overwrite cannot be attributed, so LEAPP warns instead of guessing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Lionel Gulich <lgulich@nvidia.com>
|
@lgulich, Issue 1 you defined is fixed as part of #33. it provides larger capabilities of tracing mutations through views of tensors. issue 2 is a real problem however it might be possible to fix it through annotate.register_buffer()? this is the cannonical way to identify buffers like this. however register buffer needs to be declared after input tensors. Can you try to see if that is good enough? if not I can see what I can do. the solution you proposed might be hazardous especially if someone decides to open multiple model captures at the same time and might introduce overhead. if issue 2 can't be fully solved with register buffers i can approve this PR and later update it with #33 to solve the first problem to unblock you. |
|
thanks, seems like register_buffer does solve the problem. So then we can close this MR and merge #33 instead |
Summary
Two Warp tracing fixes found while exporting a Warp geometric fabric (nvblox_next
GlobalSurfelFabric) through LEAPP. In both cases the export either failed or exported a model that silently gave wrong results after the first call.1.
wp.from_torchof a view of a traced tensor (traced[5:10],surfels[..., 0:3])APIC param 'input_0' byte size mismatch: metadata/tensor has 20 bytes, APIC expects 40.datatypes/torch/storage_root.py).2.
zero_()/fill_()of an untraced Warp buffer inside a nodeatomic_addinto it, e.g.metric.zero_()and then a launch. Automatic segments only open at the first Warp call that touches traced data. The reset therefore ran once during tracing and never on replay, and the runner accumulated across calls.input_tensorsandoutput_tensorsbelongs to that node. An overwrite of an untraced array there now opens or joins that node's segment.fill_andzero_are attributed. A kernel launch on an untraced array may read its previous contents, which is undeclared state, so it stays a user error. This keepstest_undeclared_persistent_alias_attaches_to_nothingas is.leapp.start(), so a trace aborted by an exception does not leak into the next session.Tests
New functional tests in
tests/functional_tests/test_warp_tracing.py. Inference uses inputs that differ from the trace inputs, and the reset tests run inference three times:TestWarpTorchViews.test_offset_view_reads_live_inputTestWarpTorchViews.test_strided_views_of_one_storage_are_one_segment_input, which also asserts that there is one segment inputTestWarpTorchViews.test_view_modified_in_place_failsTestWarpUntracedOverwrite.test_reset_in_same_segment_runs_every_call, which covers one segmentTestWarpUntracedOverwrite.test_reset_before_torch_op_feeds_later_segment, which covers two segments joined by a graph edgeAll 5 fail without the fix.
Full suite, run in a fresh venv (torch 2.12.1+cu130, onnxruntime-gpu, Warp
main/ 1.19.0.dev0, RTX 6000 Ada):pytest tests/gives 874 passed.With the released
warp-lang==1.18.0wheel on this machine, 37 tests fail on unmodifieddevelopas well, withFailed to load module ... .ptx. The wheel's CUDA 13.4 toolchain emits PTX that this machine's 13.0 driver cannot load. My new inference tests hit the same error there, so they are only verified on Warpmain.Notes
developafter fix: trace Warp writes into plain Torch aliases #23. fix: trace Warp writes into plain Torch aliases #23 makes the Warp array's_tensorthe traced tensor itself, so the storage checks unwrap to a plain tensor before querying the layout. Otherwise the query would be recorded as graph operations.add_0/mul_by_1no-op rules, which useabs_tol=1e-8) removes guards such assqrt(x + 1e-12), producinginf/NaNin exported models. That needs an upstream onnxscript fix.🤖 Generated with Claude Code