Skip to content

Commit 1cf1795

Browse files
committed
fix(path-c): fp8_vecmat owner-output returns caller object on native tvm-ffi route (TASK1 Cause B)
Native bridge owner-output: drop the no-op async flag so the route returns the caller's exact out object (matches the owner-output reuse contract). Pairs with the tilelang native-bridge race fix.
1 parent 17113d0 commit 1cf1795

1 file changed

Lines changed: 34 additions & 8 deletions

File tree

cppmega_mlx/nn/_tilelang/fp8_vecmat_path_c.py

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,14 +1036,27 @@ def fp8_scaled_vecmat_path_c_direct(
10361036
f"{type(exc).__name__}: {exc}"
10371037
) from exc
10381038
try:
1039-
return kernel(
1039+
# Owner-output reuse contract: write in place into ``out`` and
1040+
# return that exact object (see the note at the primary dispatch
1041+
# site below). Dropping ``_tilelang_mlx_async_owner_outputs`` is
1042+
# behavior-preserving against the non-native (slow) tvm-ffi route
1043+
# -- which always ran synchronously and returned the caller object
1044+
# -- and restores ``returned is out`` under the now-live native
1045+
# bridge, whose async path returned a fresh aliasing wrapper.
1046+
returned = kernel(
10401047
x_fp8,
10411048
scale_x,
10421049
W_fp8,
10431050
scale_w,
10441051
out,
1045-
_tilelang_mlx_async_owner_outputs=True,
10461052
)
1053+
if returned is not out:
1054+
raise FP8VecmatPathCDirectError(
1055+
"direct tvm-ffi FP8 vecmat did not return the caller-owned output"
1056+
)
1057+
return out
1058+
except FP8VecmatPathCDirectError:
1059+
raise
10471060
except Exception as exc:
10481061
try:
10491062
from tilelang.contrib.mlx_interop import DLPackInteropError
@@ -1079,13 +1092,22 @@ def fp8_scaled_vecmat_path_c_direct(
10791092
) from exc
10801093

10811094
try:
1095+
# Owner-output reuse contract: the kernel writes in place into the
1096+
# caller-owned ``C`` (== ``out``) and the route returns that exact
1097+
# object, matching the sibling matmul direct route and the non-native
1098+
# (slow) tvm-ffi route, which always returns the caller object. The
1099+
# earlier ``_tilelang_mlx_async_owner_outputs=True`` request made the
1100+
# now-live native bridge return a fresh MLX wrapper that merely *aliases*
1101+
# ``out`` (correct data, but ``returned is out`` was False). The slow
1102+
# route ignored the async flag and ran synchronously, so dropping it is
1103+
# behavior-preserving against the committed baseline while restoring the
1104+
# documented ``returned is out`` contract under the native route.
10821105
returned = kernel(
10831106
A,
10841107
A_scale,
10851108
B,
10861109
B_scale,
10871110
C,
1088-
_tilelang_mlx_async_owner_outputs=True,
10891111
)
10901112
except Exception as exc:
10911113
try:
@@ -1097,7 +1119,11 @@ def fp8_scaled_vecmat_path_c_direct(
10971119
raise FP8VecmatPathCDirectError(
10981120
f"direct tvm-ffi FP8 vecmat dispatch failed: {type(exc).__name__}: {exc}"
10991121
) from exc
1100-
return returned
1122+
if returned is not C:
1123+
raise FP8VecmatPathCDirectError(
1124+
"direct tvm-ffi FP8 vecmat did not return the caller-owned output"
1125+
)
1126+
return C
11011127

11021128

11031129
def fp8_scaled_vecmat_path_c(
@@ -1116,10 +1142,10 @@ def fp8_scaled_vecmat_path_c(
11161142
``x_fp8`` is ``(K,)`` uint8 e4m3 storage and ``W_fp8`` is transposed
11171143
``(N, K)`` storage, matching Path B. ``scale_x`` is scalar; ``scale_w`` may
11181144
be scalar or per-output ``(N,)``. When ``out`` is provided, dispatches via
1119-
tvm-ffi into that caller-owned output and returns the MLX graph output that
1120-
aliases ``out``. Evaluating the returned value schedules the write; reading
1121-
``out`` after that observes the same storage. Without ``out``, this function
1122-
fails explicitly: there is no non-owner-output Path C dispatch surface.
1145+
tvm-ffi into that caller-owned output and returns that same ``out`` object
1146+
(owner-output reuse contract, matching the sibling matmul direct route and
1147+
the non-native tvm-ffi route). Without ``out``, this function fails
1148+
explicitly: there is no non-owner-output Path C dispatch surface.
11231149
"""
11241150

11251151
if out is not None:

0 commit comments

Comments
 (0)