Skip to content

[Launcher] Add packed-launch fast path (Fix E) - #7704

Draft
NathanVoldman wants to merge 2 commits into
mainfrom
dev/nvoldman/fix-torchbench-regression-Fix-E
Draft

[Launcher] Add packed-launch fast path (Fix E)#7704
NathanVoldman wants to merge 2 commits into
mainfrom
dev/nvoldman/fix-torchbench-regression-Fix-E

Conversation

@NathanVoldman

Copy link
Copy Markdown
Contributor

Adds an optional "packed launch" path to the XPU launcher that resolves pointer arguments once in Python and passes them to C as a flat void*[] buffer, bypassing the per-arg PyObject_GetAttr + PyObject_CallNoArgs chain in extractPointer.

C-side additions (driver.c):

  • buildRawKernelArgIndices(): walks arg_annotations to map signature slots to raw-args-tuple indices; sets packable=false on ARG_TUPLE.
  • build_pack_layout(): computes pointer_raw_indices + pack_buffer_size for a given (kernel_signature, arg_annotations) pair. Returns packable=false when annotations contain tuple-nested entries or when there are no pointer args (packing has no upside).
  • launch_packed(): counterpart to launch() that reads pointer values from a caller-provided y*-buffer instead of extracting them from Python objects one at a time. Scalar args still go through their normal extractor.

Python-side additions (driver.py):

  • SpirvUtils splits DLL symbols into _REQUIRED_METHODS and _OPTIONAL_METHODS. launch_packed / build_pack_layout are optional and gated by has_packed_launch; older / stripped builds transparently fall back to classic launch().
  • XPULauncher.init probes eligibility once at specialization time: when the kernel has pointer args and no tensordesc / tuple annotations, it pre-allocates a bytearray pack buffer and a memoryview cast to native pointer size, and selects launch_packed as the launcher.
  • XPULauncher.call takes a packed fast path when enabled: iterate _pointer_arg_indices, resolve each arg via numbers.Integral / .data_ptr(), write into the pack buffer, then hand C the buffer + args tuple.
  • Escape hatch: TRITON_INTEL_DISABLE_PACKED_LAUNCH=1 forces the classic launch() path.

Fix E is independent of Fix A (KernelInfo cache) and Fix B (data_ptr intern) — this branch contains only Fix E on top of origin/main.

New contributor declaration

  • I am not making a trivial change, such as fixing a typo in a comment.

  • I have written a PR description following these
    rules.

  • I have run pre-commit run --from-ref origin/main --to-ref HEAD.

  • Select one of the following.

    • I have added tests.
      • /test for lit tests
      • /unittest for C++ tests
      • /python/test for end-to-end tests
    • This PR does not need a test because flow run in every launch.
  • Select one of the following.

    • I have not added any lit tests.
    • The lit tests I have added follow these best practices,
      including the "tests should be minimal" section. (Usually running Python code
      and using the instructions it generates is not minimal.)

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an optional packed-pointer fast path to reduce XPU kernel launch overhead.

Changes:

  • Adds packed layout construction and native packed launching.
  • Selects packed launching for eligible kernels with compatibility fallbacks.
  • Adds an environment-variable escape hatch.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
third_party/intel/backend/driver.py Selects, configures, and invokes packed launches.
third_party/intel/backend/driver.c Builds pack layouts and launches using packed pointers.
Suppressed comments (1)

third_party/intel/backend/driver.c:1403

  • The exported helper assumes the signature length equals the number of ARG_KERNEL annotations, then uses the unchecked PyList_GET_ITEM macro. A mismatched direct call can read outside the list and crash Python. Check the lengths and raise before entering this loop.
    for (Py_ssize_t i = 0; i < num_sig_args; ++i) {
      if (sig[i] == EXTRACTOR_POINTER_INDEX) {
        PyObject *raw_idx =
            PyList_GET_ITEM(kernel_arg_raw_indices, i); // borrowed

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

bool packable = true;
Py_ssize_t raw_i = 0;
for (Py_ssize_t i = 0; i < n; ++i) {
PyKernelArgObject *annotation = (PyKernelArgObject *)items[i];
Comment thread third_party/intel/backend/driver.c Outdated
Comment on lines +1650 to +1651
if (!launchHook(launch_enter_hook, launch_metadata)) {
RELEASE_AND_FAIL();
Comment thread third_party/intel/backend/driver.py Outdated
Comment on lines +829 to +832
if not isinstance(result, int):
# Same message the classic path raises when data_ptr()
# returns a non-int (PyLong_AsVoidPtr -> TypeError).
raise TypeError("Pointer argument must be either uint64 or have data_ptr method")
Comment on lines +714 to +715
if ((not disable_packed) and launch_packed_fn is not None and build_pack_layout_fn is not None
and not has_tensordesc):
NathanVoldman and others added 2 commits August 9, 2026 14:15
Adds an optional "packed launch" path to the XPU launcher that resolves
pointer arguments once in Python and passes them to C as a flat void*[]
buffer, bypassing the per-arg PyObject_GetAttr + PyObject_CallNoArgs
chain in extractPointer.

C-side additions (driver.c):
  - buildRawKernelArgIndices(): walks arg_annotations to map signature
    slots to raw-args-tuple indices; sets packable=false on ARG_TUPLE.
  - build_pack_layout(): computes pointer_raw_indices + pack_buffer_size
    for a given (kernel_signature, arg_annotations) pair. Returns
    packable=false when annotations contain tuple-nested entries or
    when there are no pointer args (packing has no upside).
  - launch_packed(): counterpart to launch() that reads pointer values
    from a caller-provided y*-buffer instead of extracting them from
    Python objects one at a time. Scalar args still go through their
    normal extractor.

Python-side additions (driver.py):
  - SpirvUtils splits DLL symbols into _REQUIRED_METHODS and
    _OPTIONAL_METHODS. launch_packed / build_pack_layout are optional
    and gated by has_packed_launch; older / stripped builds transparently
    fall back to classic launch().
  - XPULauncher.__init__ probes eligibility once at specialization time:
    when the kernel has pointer args and no tensordesc / tuple annotations,
    it pre-allocates a bytearray pack buffer and a memoryview cast to
    native pointer size, and selects launch_packed as the launcher.
  - XPULauncher.__call__ takes a packed fast path when enabled: iterate
    _pointer_arg_indices, resolve each arg via numbers.Integral / .data_ptr(),
    write into the pack buffer, then hand C the buffer + args tuple.
  - Escape hatch: TRITON_INTEL_DISABLE_PACKED_LAUNCH=1 forces the
    classic launch() path.

Fix E is independent of Fix A (KernelInfo cache) and Fix B (data_ptr
intern) — this branch contains only Fix E on top of origin/main.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds coverage in python/test/unit/intel/test_driver.py for the packed-launch
fast path (Fix E) added by the preceding commit:

  - test_packed_launch_selected_by_default: probes build_pack_layout with
    the annotation/signature shape of a pointer-heavy kernel and confirms
    eligibility (packable=True, correct pointer_indices, correct buffer
    size), plus end-to-end correctness through the launcher.
  - test_packed_launch_disable_env: TRITON_INTEL_DISABLE_PACKED_LAUNCH=1
    forces the classic path; kernel output must still be correct.
  - test_packed_launch_none_pointer: `None` as a pointer arg is accepted.
  - test_packed_launch_int_pointer: a Python int used as a raw pointer
    value is accepted.
  - test_packed_launch_scalar_and_pointer_coexist: mixed pointer + scalar
    kernels produce correct output.
  - test_packed_vs_classic_parity: same kernel + inputs produce the same
    output whether packed is enabled or forced off.
  - test_packed_launch_reentrant_enter_hook: regression test for the
    launch_packed snapshot-before-hook fix — a hook that re-enters the
    same kernel with different tensors must not corrupt the outer
    launch's pointer values.
  - test_build_pack_layout_rejects_non_pykernelarg: validates the
    PyObject_TypeCheck guard in buildRawKernelArgIndices — passing [None]
    as arg_annotations raises TypeError instead of segfaulting.
  - test_build_pack_layout_reports_no_pointer_kernel: kernels with no
    pointer args report packable=False.
  - test_build_pack_layout_arg_tuple_falls_back: ARG_TUPLE annotations
    force packable=False so the launcher falls back to the classic path.

All packed-launch tests are gated on build presence of the Fix E C
symbols (launch_packed / build_pack_layout) so older builds skip cleanly.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@NathanVoldman
NathanVoldman force-pushed the dev/nvoldman/fix-torchbench-regression-Fix-E branch from d9633d3 to 9cdf771 Compare August 9, 2026 11:22
@NathanVoldman
NathanVoldman marked this pull request as draft August 10, 2026 09:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants