Skip to content
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
31b9686
feat(rocke): add cross-workgroup fence and flag IR ops
jakpiase Oct 5, 2026
bcd26d5
feat(rocke): add CK stream-K iteration partitioner helper
jakpiase Oct 5, 2026
e52ebbd
feat(rocke): add stream-K to implicit-GEMM conv wgrad
jakpiase Oct 5, 2026
f8f8200
test(rocke): gate stream-K conv wgrad IR in both engines
jakpiase Oct 5, 2026
6cf88ca
test(rocke): add CPU and GPU tests for stream-K conv wgrad
jakpiase Oct 5, 2026
7c60580
feat(rocke): select stream-K conv wgrad through grouped conv dispatch
jakpiase Oct 5, 2026
ed7bdf9
docs(rocke): document stream-K conv wgrad
jakpiase Oct 5, 2026
91d9461
perf(rocke): size the stream-K wgrad CTA pool per reduction
jakpiase Oct 5, 2026
d738d30
feat(rocke): let grouped conv dispatch choose stream-K for wgrad
jakpiase Oct 5, 2026
7484126
perf(rocke): count the stream-K wgrad pool in CTAs per CU
jakpiase Oct 5, 2026
6357338
Merge origin/develop into users/jpiasecki/rocke-streamk-wgrad
jakpiase Oct 6, 2026
e69bb4c
style(rocke): clang-format stream-K wgrad sources
jakpiase Oct 6, 2026
082f584
fix(rocke): harden stream-K wgrad validation and HIP flag lowering
jakpiase Oct 6, 2026
cb6a47b
fix(rocke): verify flag-op contracts and skip all-DP stream-K auto picks
jakpiase Oct 6, 2026
974d6de
Merge remote-tracking branch 'origin/develop' into users/jpiasecki/ro…
jakpiase Oct 8, 2026
6c6bf35
fix(rocke): close stream-K wgrad review gaps in both engines
jakpiase Oct 8, 2026
4c31596
refactor(rocke): move wgrad stream-K from the dispatcher to the sweep
jakpiase Oct 8, 2026
8b0f49b
fix(rocke): type-check the flag ops and reject bad sync attrs in both…
jakpiase Oct 8, 2026
7c820fe
fix(rocke): align the stream-K wgrad host API and validator with Python
jakpiase Oct 8, 2026
4cf1e5c
fix(rocke): handle all-DP stream-K partitions in the sweep and share …
jakpiase Oct 8, 2026
f27ebe7
Merge remote-tracking branch 'origin/develop' into users/jpiasecki/ro…
jakpiase Oct 9, 2026
33e50de
style(rocke): black-format the stream-K wgrad validator test
jakpiase Oct 9, 2026
2845319
perf(rocke): cache only a slice of the stream-K wgrad kernels
jakpiase Oct 12, 2026
54fee46
Merge remote-tracking branch 'origin/develop' into users/jpiasecki/ro…
jakpiase Oct 12, 2026
e21ce59
Merge branch 'develop' into users/jpiasecki/rocke-streamk-wgrad
jakpiase Oct 12, 2026
4907c5e
Merge branch 'develop' into users/jpiasecki/rocke-streamk-wgrad
jakpiase Oct 12, 2026
311102a
Merge branch 'develop' into users/jpiasecki/rocke-streamk-wgrad
jakpiase Oct 12, 2026
fd1b1c3
Merge branch 'develop' into users/jpiasecki/rocke-streamk-wgrad
jakpiase Oct 13, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ test_categories:
- "rocke_arch_target_identity"
- "rocke_ir_serialize_roundtrip"
- "rocke_mma_frag_ssot"
- "rocke_streamk_iter_partition"
- "rocke_tiled_attention_2d_reentrancy"
- "rocke_python_import_smoke"
- "rocke_golden_static"
Expand All @@ -47,6 +48,7 @@ test_categories:
- "rocke_arch_target_identity"
- "rocke_ir_serialize_roundtrip"
- "rocke_mma_frag_ssot"
- "rocke_streamk_iter_partition"
- "rocke_tiled_attention_2d_reentrancy"
- "rocke_python_import_smoke"
- "rocke_golden_static"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,27 @@ def main() -> int:
choices=["fp16", "bf16", "fp32"],
help="data type (default: fp16)",
)
Comment thread
jakpiase marked this conversation as resolved.
Resolved
parser.add_argument(
"--streamk",
default="auto",
choices=["auto", "off", "dp_sk", "persistent"],
Comment thread
jakpiase marked this conversation as resolved.
Resolved
help=(
"wgrad only: auto (default) lets the dispatcher pick stream-K where it "
"is expected to win; off never uses it; dp_sk (data-parallel + "
"stream-K CTAs) / persistent (a fixed CTA pool round-robining tiles) "
"force it"
),
)
parser.add_argument(
"--streamk-reduction",
default="auto",
dest="streamk_reduction",
choices=["auto", "linear", "tree", "workspace"],
help=(
"wgrad stream-K fixup: linear/tree (deterministic flag hand-off) or "
"workspace (f32 scratch atomics + reduce kernel); auto = workspace"
),
)
parser.add_argument(
"--warmup", type=int, default=3, help="warmup iterations (default: 3)"
)
Expand Down Expand Up @@ -823,6 +844,10 @@ def _u8(t):
dtype=dtype,
direction=args.direction,
)
if args.direction == "wgrad":
req_base.update(
streamk=args.streamk, streamk_reduction=args.streamk_reduction
)
if problem.is_3d:
req_base.update(
Di=problem.Di,
Expand Down Expand Up @@ -1110,6 +1135,120 @@ def _make(*shape):
return 0


def _streamk_launcher(
*,
rt,
spec,
kernel,
arch: str,
grid,
block,
stream,
ws_dev,
ws_nbytes: int,
buffers,
nbytes,
compile_kernel,
KernelLauncher,
LaunchConfig,
):
"""``(launcher, kernel_name, launch(fence))`` for a stream-K wgrad spec.

Each launch resets exactly what the reduction's contract requires before
the kernel runs: the flag table for linear/tree (dW is stored once by the
tile owner), the f32 scratch for the workspace reduction, which is then
cast into dW by the Stage 2 reduce kernel on the same stream.
"""
from kernels.common.conv_implicit_gemm_wgrad import (
wgrad_streamk_launch_values,
wgrad_streamk_signature,
wgrad_streamk_workspace_layout,
)
from kernels.common.conv_wgrad_workspace_reduce import (
WgradReduceSpec,
build_conv_wgrad_workspace_reduce,
wgrad_reduce_grid,
wgrad_reduce_signature,
)

dY_dev, X_dev, dW_dev = buffers
dY_nb, X_nb, dW_nb = nbytes
artifact = compile_kernel(kernel, arch=arch)
launcher = KernelLauncher(
hsaco=artifact.hsaco,
kernel_name=artifact.kernel_name,
signature=wgrad_streamk_signature(spec),
)
reducer = None
extra = {}
if spec.streamk_reduction == "workspace":
extra = dict(ws_ptr=ws_dev, ws_bytes=ws_nbytes)
reset_bytes = ws_nbytes
else:
flags_bytes, _ = wgrad_streamk_workspace_layout(spec, arch=arch)
extra = dict(sk_flags=ws_dev, sk_partials=ws_dev + flags_bytes)
reset_bytes = flags_bytes
values = wgrad_streamk_launch_values(
spec,
dY_dev,
X_dev,
dW_dev,
dY_nb,
X_nb,
dW_nb,
arch=arch,
**extra,
)
if spec.streamk_reduction == "workspace":
p = spec.problem
rspec = WgradReduceSpec(
problem=p,
dtype_d=spec.data.dtype_d,
groups=p.groups,
ws_replicas=spec.ws_replicas,
)
rart = compile_kernel(
build_conv_wgrad_workspace_reduce(rspec, arch=arch), arch=arch
)
reducer = KernelLauncher(
hsaco=rart.hsaco,
kernel_name=rart.kernel_name,
signature=wgrad_reduce_signature(rspec),
)
rvalues = {
"ws_ptr": ws_dev,
"dw_ptr": dW_dev,
"wg_M": spec.wg_M,
"wg_N": spec.wg_N,
"ws_bytes": ws_nbytes,
"dw_bytes": dW_nb,
"groups": p.groups,
}

def _launch(fence: bool):
if reset_bytes:
rt.memset(ws_dev, 0, reset_bytes)
launcher(
values,
config=LaunchConfig(
grid=grid, block=block, stream=stream, fence=fence and reducer is None
),
)
if reducer is not None:
reducer(
rvalues,
config=LaunchConfig(
grid=wgrad_reduce_grid(rspec),
block=(rspec.block_size, 1, 1),
stream=stream,
fence=fence,
),
)

name = artifact.kernel_name + ("+cast" if reducer is not None else "")
return launcher, name, _launch


def _run_wgrad(
*,
args,
Expand Down Expand Up @@ -1138,6 +1277,9 @@ def _run_wgrad(
_DEFAULT_TILE_M as _WGRAD_REDUCE_TILE_M,
_DEFAULT_TILE_N as _WGRAD_REDUCE_TILE_N,
)
from kernels.common.conv_implicit_gemm_wgrad import (
wgrad_streamk_workspace_nbytes,
)

_u8 = u8
p = problem
Expand Down Expand Up @@ -1226,6 +1368,9 @@ def _make(*shape):
launcher, ws_nbytes = build_implicit_gemm_conv_wgrad_two_stage(
instance_spec, arch=arch
)
elif instance_spec.streamk != "off":
kernel = build_implicit_gemm_conv_wgrad(instance_spec, arch=arch)
ws_nbytes = wgrad_streamk_workspace_nbytes(instance_spec, arch=arch)
else:
kernel = build_implicit_gemm_conv_wgrad(instance_spec, arch=arch)
ws_nbytes = 0
Expand All @@ -1244,7 +1389,27 @@ def _make(*shape):
# factor from z entirely, so every grouped launch covered group 0 only.
grid = _wgrad_grid(dspec, req)

if instance_spec.two_stage:
if instance_spec.streamk != "off":
if ws_dev is not None:
rt.free(ws_dev)
ws_dev = rt.alloc(max(ws_nbytes, 4))
launcher, kernel_name, _launch = _streamk_launcher(
rt=rt,
spec=instance_spec,
kernel=kernel,
arch=arch,
grid=grid,
block=block,
stream=stream,
ws_dev=ws_dev,
ws_nbytes=ws_nbytes,
buffers=(dY_dev, X_dev, dW_dev),
nbytes=(dY_t.nbytes, X_t.nbytes, dW_t.nbytes),
compile_kernel=compile_kernel,
KernelLauncher=KernelLauncher,
LaunchConfig=LaunchConfig,
)
elif instance_spec.two_stage:
if ws_dev is not None:
rt.free(ws_dev)
ws_dev = rt.alloc(ws_nbytes)
Expand Down
Loading
Loading