Skip to content

refactor(rocke): Split the torch-optional path from a torch-free hip-only core#9302

Open
shumway wants to merge 6 commits into
developfrom
users/shumway/rocke-runtime-torch-split
Open

refactor(rocke): Split the torch-optional path from a torch-free hip-only core#9302
shumway wants to merge 6 commits into
developfrom
users/shumway/rocke-runtime-torch-split

Conversation

@shumway

@shumway shumway commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Issue ID : AICK-1518

Summary

Reorganize the rocke platform runtime (dnn-providers/hip-kernel-provider/rocke/platform/python/rocke/runtime/) so the hip-only path is torch-free by construction while torch stays optional. No behavior change; the public rocke.runtime API (__all__) is unchanged. This is a step toward removing the python torch dependency from rocKE.

The hip_module.py had picked up a lot of torch logic. With this change, hip_module.py is now consistent with its docstring: a minimal ctypes wrapper over libamdhip64.so for the hipModule API.

The extra bloat from hip_module.py is now split out into three modules, and we renamed one module:

  • runtime_coexistance.py to logically bind using either system or torch-bundled discovery of ROCm.
  • _ctypes_bind.py for _LaxyFn needed by both hip_module.py and comgr.py.
  • packing.py for args packing.
  • torch_interop.py was torch_module.py, renamed to clarify that it is glue for torch inter operability.

The changes are:

  • Extract runtime_coexistence.py (which ROCm runtime we bind to, and whose: torch-bundled vs system discovery).
  • Extract _ctypes_bind.py (_LazyFn); both comgr and hip_module now depend on them — removing the inverted comgr → hip_module import.
  • Extract packing.py (torch-agnostic pack_args / pack_args_kernelparams), so the numpy/manifest path no longer imports from a torch-named module.
  • Rename torch_module.pytorch_interop.py (it holds torch-tensor launch glue, not a wrapped "torch module"); resolve_stream stays there (torch-aware but torch-optional).
  • Reframe the Runtime._pending_args keep-alive queue as a backend-agnostic, stream-scoped lifetime manager.

Risk Assessment

Risk 3 (core runtime subsystem, multi-file), low residual. Behavior-preserving, host-only Python (no kernel/device/default-selection change), public import surface unchanged. Characterization tests were landed first to lock the moved
behaviors, and the host suite stayed green (207 passed / 17 skipped) at every commit. Verified: with import torch poisoned, the hip-only core imports, packs args, and constructs Runtime; no core module imports torch at module scope
(comgr.prefer_bundled_lib keeps one deliberate, documented function-local import torch).

Device / Architecture Coverage

Host-only Python plumbing; no kernel, dispatch, or default-selection change. Passing PR CI is sufficient — no device sweep required. The byte-identity parity gate does not apply (the runtime layer is downstream of .ll emission; there is
no C++ runtime twin).

Testing Summary

  • Host unit + characterization suite for the runtime reorg, in the torch-free platform venv.

Testing Checklist

  • rocke platform host tests - python -m pytest tests/test_rocke.py (platform/.venv) - Status: Passed (207 passed, 17 skipped)
  • Full platform runner (guard + byte-identity gate + ctest) - python tests/run_all.py - Status: Not run
  • PR CI - GitHub PR checks - Status: Pending

Flags / Guardrails

None. Behavior-preserving refactor; no new runtime behavior or feature flag.

Adjacent Tests Considered

The 13 new characterization tests cover the moved seams (args-buffer keep-alive on async vs blocking launch; resolve_stream present/absent/passthrough; pack_args kernarg-alignment ABI + kernelparams agreement; lib-discovery
ordering). The full test_rocke.py (224 host tests) exercises the runtime, launcher, and instance-build paths that import these modules and stayed green.

Technical Changes

  • 6 commits: characterization tests → coexistence/_ctypes_bind extraction → packing extraction → torch_moduletorch_interop rename → Runtime docstring reframe → doc alignment. Each behavior-preserving.
  • Updated dsl_docs + AGENTS/BUILD cross-references to the new module layout.

shumway and others added 6 commits July 10, 2026 16:15
…e reorg

Pin the behaviors an upcoming rocke.runtime module split must preserve, so
the moves are provably behavior-preserving rather than a leap. All host-only
(no GPU), run in the torch-free platform venv.

- TestRuntimeLaunchKeepAlive: async launch parks the extra-path args buffer
  until drain (parked extra ptr == addressof(args_buf)); launch_blocking
  parks nothing and syncs exactly once. This args-buffer lifetime is a
  non-torch invariant that protects numpy callers too.
- TestResolveStream: passthrough of a nonzero handle without touching torch;
  fall back to the null stream when torch is absent; substitute torch's
  current stream when present (the tripwire against a silent collapse to 0
  inside a torch process).
- TestPackArgsKernargABI: AMDGPU kernarg natural-alignment (padding before a
  trailing pointer after three i32s), pack_args/pack_args_kernelparams value
  agreement, and the missing-arg / unknown-type guards.
- TestLibDiscoveryOrder: newest-ROCm-first version ordering, env override
  first in candidate resolution, and that the torch-bundled probe never
  imports torch for the loader side effect.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Split the shared library-resolution and lazy-ctypes plumbing out of
hip_module.py so the HIP and comgr wrappers become peers over a shared
foundation instead of comgr reaching up into hip_module.

- runtime_coexistence.py: "which ROCm runtime do we bind to, and whose" --
  torch-bundled vs system-install discovery (_torch_bundled_lib,
  _rocm_sdk_dll, _rocm_root_libdirs, _version_key, _candidate_lib_paths,
  _add_dll_dir, _IS_WINDOWS). Framed as sharing one loaded HIP/comgr
  runtime instance (not an HSA context), the distinction that avoids the
  hipError(500) named-symbol-not-found from a double-loaded runtime.
- _ctypes_bind.py: the _LazyFn lazy-binding helper (pure ctypes mechanism).
- hip_module.py and comgr.py now import both from these modules; the
  inverted comgr->hip_module import is removed. _ensure_hip_init and
  get_device_arch stay in hip_module with the HIP function table (they
  bind the primary context / read gcnArchName).
- Bodies moved verbatim; only the _version_key `import re` was hoisted to
  module scope. Doc cross-refs updated (comgr, lower_llvm, AGENTS, BUILD).

Behavior-preserving: full host suite 207 passed / 17 skipped, unchanged.
The characterization tests from the prior commit now import the moved
helpers from runtime_coexistence.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
pack_args / pack_args_kernelparams / _as_ptr are torch-agnostic (they
duck-type device pointers on .data_ptr() and accept plain ints), yet
lived in torch_module.py -- so a torch-free caller (heuristics/_measure_moe,
whose own docstring says "No torch dependency") had to import from a module
named torch_module. Move them to a new torch-free packing.py (imports only
ctypes/struct/typing) that the numpy/manifest and torch paths both use.

Re-pointed launcher, heuristics/_measure_moe (+ its docstring), the runtime
__init__ re-export, and the pack_args characterization tests. torch_module
shed its now-unused ctypes/struct/List imports. Public rocke.runtime.pack_args
path is unchanged (re-exported via __init__).

Behavior-preserving: host suite 207 passed / 17 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
torch_module was a false cognate beside hip_module (which genuinely wraps
the hipModule API) -- there is no "torch module" being wrapped. After the
packing extraction, what remains is torch-tensor launch glue: resolve_stream,
empty_workspace, launch_torch_kernel. Rename to torch_interop to name the
role. resolve_stream stays here (it is torch-aware, just torch-optional).

Re-pointed the runtime __init__ import + layer map, launcher, and the
resolve_stream characterization tests. Updated the documented public path
and the dsl_docs surface (api_index split into packing/torch_interop
sections; file_index rows for the new runtime_coexistence / _ctypes_bind /
packing / torch_interop modules; BUILD/AGENTS/mental_model/limitations/
runbook/manifest/comgr doc refs), routing pack_args mentions to packing and
module/stream mentions to torch_interop.

Behavior-preserving: host suite 207 passed / 17 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…stic

The _pending_args FIFO reads as torch machinery, but it is a stream-scoped
lifetime manager: the bucket only ever holds ctypes buffers + HIP events,
retain_for_stream takes *objects: Any and filters ints/None, and Runtime
never imports torch. It serves two lifetimes -- the ctypes args buffer
(non-torch; parked on every async launch, numpy callers included) and any
caller-retained object (torch tensors being the motivating case, retained
by the torch-aware launcher). Reframe the class comment to say so, so a
future reader doesn't "tidy up" by moving retention into a torch module --
which would split one FIFO across two owners and drop the args-buffer
keep-alive for non-torch callers.

Docstring-only; no behavior change. Host suite 207 passed / 17 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Holistic review follow-ups (no logic change):
- torch_interop.py module docstring: drop the stale "packed from
  torch.Tensor.data_ptr()" claim (packing moved to packing.py) and the
  torch-tensor-only charter; name its torch-optional resolve_stream tenant.
- packing.py: error text "unsupported torch arg type" -> "kernel arg type"
  so the torch-agnostic module doesn't blame torch on the numpy path.
- __init__ layer map: name the torch-free-core / torch-aware-edge seam and
  give _ctypes_bind its own line.
- file_index intro: "primary public exports" -> "primary contents", since
  whole-module-private files (runtime_coexistence, _ctypes_bind) list their
  key internal helpers.

Host suite 207 passed / 17 skipped.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@therock-pr-bot

therock-pr-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
🌿 Branch Name ✅ Pass
📝 PR Title/Description ✅ Pass
Forbidden Files ✅ Pass
🧪 Unit Test ✅ Pass
🔎 pre-commit ✅ Pass
🚫 Draft PR 🔜 To Be Enabled
🚩 Feature Flag 🔜 To Be Enabled
📊 Code Coverage 🔜 To Be Enabled
🤖 therock-pr-bot ✅ Pass

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

@therock-pr-bot

therock-pr-bot Bot commented Jul 11, 2026

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

@shumway shumway marked this pull request as ready for review July 11, 2026 00:20
@shumway shumway requested review from a team as code owners July 11, 2026 00:20
@shumway shumway changed the title [AICK-1518] refactor(rocke/runtime): split the torch-optional path from a torch-free hip-only core refactor(rocke): Split the torch-optional path from a torch-free hip-only core Jul 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant