Official agent skill

Autows Authoring

by facebookexperimental in facebookexperimental/triton

Author Triton kernels with automatic warp specialization (AutoWS).

OfficialMITAuto-check passedDevelopment

Install Autows Authoring

skills CLI
$ npx skills add facebookexperimental/triton --skill autows-authoring -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install facebookexperimental/triton autows-authoring --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/facebookexperimental/triton.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/autows-authoring .claude/skills/autows-authoring && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
autows-authoring
GitHub stars
201
Token cost
~7.1k tokens
SKILL.md length
2,177 words
Files
1
Skills in repo
18
Repo updated
First seen
Licence
MIT

At a glance

Author Triton kernels with automatic warp specialization (AutoWS).

  • Works in 3 steps: Set TRITON_USE_META_WS=1 (or… → Use tl.range(..., warp_specialize=True)… → Pass num_warps >= 4 at launch
  • Writing new AutoWS kernels
  • SKILL.md covers Key Authoring Rules, Enabling AutoWS, tl.range() Kwargs Reference and JIT-Level Options, plus 7 more sections
  • Calls python

What it does

Autows Authoring is an agent skill from facebookexperimental/triton, published by the product's own GitHub organization. Author Triton kernels with automatic warp specialization (AutoWS). Use when writing new AutoWS kernels, adding warpspecialize=True to tl.range loops, choosing tl.range kwargs and JIT options, debugging why WS was not applied, or structuring a kernel to work with both Meta WS and upstream OAI Triton. Covers GEMM and Flash Attention patterns on Hopper and Blackwell.

Its SKILL.md is about 7.1k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development, covering GPU and accelerator computing. The repository describes itself as: Github mirror of trition-lang/triton repo. The licence is MIT.

When your agent uses it

  • Writing new AutoWS kernels
  • Adding warpspecialize=True to tl.range loops
  • Choosing tl.range kwargs and JIT options
  • Debugging why WS was not applied

Example prompts

  • “/autows-authoring”

Requirements

  • Python 3

Workflow steps

3 steps, taken from the first numbered list in SKILL.md.

  1. Set TRITON_USE_META_WS=1 (or triton.knobs.nvidia.use_meta_ws = True)
  2. Use tl.range(..., warp_specialize=True) on your loop
  3. Pass num_warps >= 4 at launch

What it can do on your machine

Read from SKILL.md and the folder at commit 6f3dd70. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    Shell commands in SKILL.md call:

    • python

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Autows Authoring loads about 7.1k tokens when it runs. Until then it costs about 96 tokens; SKILL.md has 2,177 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~96
When it runs · the whole SKILL.md, loaded when a task matches
~7.1k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from facebookexperimental/triton at commit 6f3dd70, republished under its MIT licence (© facebookexperimental). 2,177 words, ~7,094 tokens.

Download SKILL.mdSave it as .claude/skills/autows-authoring/SKILL.md (or your agent's skills folder).
name
autows-authoring
description
Author Triton kernels with automatic warp specialization (AutoWS). Use when writing new AutoWS kernels, adding warp_specialize=True to tl.range loops, choosing tl.range kwargs and JIT options, debugging why WS was not applied, or structuring a kernel to work with both Meta WS and upstream OAI Triton. Covers GEMM and Flash Attention patterns on Hopper and Blackwell.

AutoWS Kernel Authoring Guide

AutoWS is Meta's compiler-driven warp specialization for Triton kernels. Instead of manually writing producer/consumer partitions with TLX primitives (barriers, tlx.async_tasks, local_alloc), you annotate tl.range() with warp_specialize=True and the compiler automatically partitions ops, inserts barriers, allocates SMEM/TMEM buffers, and handles multi-buffering.

Minimal recipe:

  1. Set TRITON_USE_META_WS=1 (or triton.knobs.nvidia.use_meta_ws = True)
  2. Use tl.range(..., warp_specialize=True) on your loop
  3. Pass num_warps >= 4 at launch

Related skills: autows-testing (run tests), ir-debugging (IR dumps), autows-docs (compiler internals).


Key Authoring Rules

  1. Place warp_specialize=True on the outermost/persistent loop. For persistent kernels, annotate the tile loop (tl.range(start_pid, num_tiles, NUM_SMS, warp_specialize=True)), not the inner K-reduction loop. The inner loop uses plain range(). For non-persistent kernels, annotate the main compute loop.

  2. Use TMA loads. AutoWS partitions loads into a producer warp group and compute into consumer warp groups. This partitioning is most effective with TMA descriptor loads (a_desc.load(...)) rather than pointer-based tl.load(). TMA enables async bulk copies that the producer can issue independently while consumers compute. All reference kernels use TensorDescriptor + desc.load()/desc.store().

  3. Memory allocation and partition scheduling kwargs are Meta-only. The tl.range() kwargs for controlling memory allocation (smem_alloc_algo, tmem_alloc_algo, smem_budget, smem_circular_reuse) and partition scheduling (merge_epilogue, merge_correction, merge_epilogue_to_computation, separate_epilogue_store) are consumed exclusively by Meta's WS passes. They do not exist in OSS Triton's tl.range() — see OSS Fallback for how to gate them.

  4. Compute the post-loop epilogue from the genuine MMA accumulator — never a synthetic matmul. The partition scheduler keeps a post-loop reduction/gate/epilogue only if it sits in a real MMA's backward slice. If the reduction is fed by a synthetic matmul inserted only to create an MMA (e.g. (x·x)@e0 to get a row-sum), the post-loop region belongs to no genuine MMA and the scheduler elides the entire epilogue: the kernel still emits ttg.warp_specialize and passes a structural WS check, but the tl.sum / normalize / tt.store ops are all dropped and the output is unwritten garbage (a silent correctness failure, not a compile error). Reduce or gate from the real A@B accumulator instead. Confirm the WS TTGIR has a dedicated "epilogue" Meta partition and that the store ops survive.


Enabling AutoWS

Environment variable (recommended for running kernels from the command line):

bash
TRITON_USE_META_WS=1 python my_kernel.py

Also add TRITON_USE_META_WS=1 to the kernel script's module docstring so users know it's required:

python
"""
My AutoWS GEMM kernel.

Usage:
    TRITON_USE_META_WS=1 python my_gemm.py
"""

Programmatic (recommended for correctness tests only):

python
with triton.knobs.nvidia.scope():
    triton.knobs.nvidia.use_meta_ws = True
    # ... launch kernel ...

Use triton.knobs.nvidia.scope() in correctness tests so the knob is automatically restored after the test, preventing state leakage between test cases. Do NOT use scope() for actual runtime/benchmark scripts — use the TRITON_USE_META_WS=1 env var instead.

TRITON_USE_META_WS is a cache-invalidating env var (listed in include/triton/Tools/Sys/GetEnv.hpp), meaning changing it forces recompilation.

Additional Environment Variables
Env VarDefaultPurpose
TRITON_USE_META_WSFalseMaster switch for Meta WS vs upstream OAI WS
TRITON_DISABLE_WSBARRIER_REORDERFalseDisable WS barrier reordering
TRITON_ENABLE_INTERLEAVE_TMEMTrueInterleave TMEM pass (Blackwell)

Source: python/triton/knobs.py lines 502-534


tl.range() Kwargs Reference

Defined in python/triton/language/core.py (tl.range.__init__).

Core
KwargTypeDefaultDescription
warp_specializeboolFalseEnable AutoWS on this loop
flattenboolFalseLoop flattening for persistent kernels. WARNING: flatten=True currently does NOT warp-specialize — the kernel runs but skips WS
data_partition_factorint/NoneNoneSplit work across N data partitions. None/1 = no split, 2 = splits BLOCK_M in half. Requires sufficient BLOCK_SIZE_M (256 for Blackwell dp=2, 128 for Hopper dp=2)
Memory Allocation (Meta WS only)

These kwargs control how the compiler allocates SMEM/TMEM buffers. They are consumed by WSMemoryPlanner.cpp via loop attributes.

KwargTypeDefaultDescription
smem_alloc_algoint/NoneNoneSMEM allocation strategy (0 or 1). Strategy 1 is preferred for FA kernels
tmem_alloc_algoint/NoneNoneTMEM allocation strategy (Blackwell only)
smem_budgetint/NoneNoneOverride SMEM budget in bytes
smem_circular_reusebool/NoneNoneEnable circular reuse of SMEM buffers
Partition Scheduling (Meta WS only)

These kwargs control how PartitionSchedulingMeta assigns ops to partitions. They override pass-level defaults (all false) via per-loop attributes, read at PartitionSchedulingMeta.cpp lines 2614-2629.

KwargTypeDefaultDescription
merge_epilogueboolFalseMerge epilogue ops into the computation/correction/reduction partition
merge_correctionboolFalseMerge softmax correction ops into the computation partition
merge_epilogue_to_computationboolFalseMerge epilogue ops directly to the computation partition
separate_epilogue_storeboolFalseSeparate epilogue store ops into their own 1-warp partition

JIT-Level Options

Passed at kernel launch time. Defined in CUDAOptions at third_party/nvidia/backend/compiler.py lines 145-180.

OptionTypeDefaultDescription
num_warpsint4Total warps. Must be >= 4 and power of 2 for WS
num_stagesint3Pipeline depth / multi-buffer count
minRegAutoWSint24Min registers for non-tensor partitions. Divisible by 8
maxRegAutoWSint/NoneNoneMax registers for tensor partitions. Divisible by 8
pingpongAutoWSboolFalseEnable ping-pong barriers between two consumer partitions
early_tma_store_loweringboolFalseLower TMA stores before partition scheduling
Register Budget (minRegAutoWS / maxRegAutoWS)

These control how the 64K hardware register file is divided across warp-specialized partitions. Each partition runs a subset of warps and can have a different register cap (emitted as PTX setmaxnreg instructions).

Partition types:

  • Non-tensor partitions — partitions without MMA/dot ops (typically the TMA load producer). These get minRegAutoWS registers.
  • Tensor partitions — partitions with MMA/dot ops (computation, correction, reduction). These get maxRegAutoWS registers (if set) or split the remainder evenly (if not set).
  • Default partition — runs outside the WS region. Gets leftover registers.

When maxRegAutoWS is NOT set (default): Non-tensor partitions get minRegAutoWS (24). Tensor partitions AND the default partition all receive sentinel value -1, meaning "split the remaining register pool evenly after deducting the fixed allocations":

regsPerThread = (totalRegs - fixedRegs) / leftoverThreads

Computed in AllocateWarpGroups.cpp lines 244-280.

When maxRegAutoWS IS set: Non-tensor partitions get minRegAutoWS. Tensor partitions get maxRegAutoWS. The default partition gets ALL leftover registers. Computed in OptimizePartitionWarps.cpp lines 295-314.

Both values must be divisible by 8 (compiler.py:140-142).

Checking Register Allocations

To see which partitions map to which register budget and verify the actual allocation:

  1. IR inspection: Set MLIR_ENABLE_DUMP=1. Look for the ttg.warp_specialize op which carries:

    • requestedRegisters = array<i32: ...> — what OptimizePartitionWarps requested
    • actualRegisters = array<i32: ...> — what AllocateWarpGroups computed
    • Array order: [default_partition, partition_0, partition_1, ...]
    • A -1 in requestedRegisters means "split evenly"
    • Example: requestedRegisters = array<i32: 24, -1, 24> means load partition gets 24, computation splits leftovers, epilogue store gets 24
  2. PTXAS log: TRITON_DUMP_PTXAS_LOG=1 prints ptxas verbose output showing register usage.

  3. PTX inspection: kernel.asm['ptx'] — search for setmaxnreg.inc.sync.aligned and setmaxnreg.dec.sync.aligned to see register reallocation at partition boundaries.


Kernel Patterns

GEMM (K-loop WS)

Warp-specialize the inner K-reduction loop. Based on matmul_kernel_tma_ws in python/test/unit/language/test_tutorial09_warp_specialization.py lines 34-94.

python
"""
GEMM with AutoWS (K-loop warp specialization).

Usage:
    TRITON_USE_META_WS=1 python my_gemm.py
"""

@triton.jit
def matmul_kernel_ws(a_desc, b_desc, c_desc, M, N, K,
                     BLOCK_SIZE_M: tl.constexpr, BLOCK_SIZE_N: tl.constexpr,
                     BLOCK_SIZE_K: tl.constexpr,
                     DATA_PARTITION_FACTOR: tl.constexpr,
                     SMEM_ALLOC_ALGO: tl.constexpr,
                     SEPARATE_EPILOGUE_STORE: tl.constexpr, ...):
    # ... pid computation ...
    accumulator = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.float32)
    for k in tl.range(
            k_tiles,
            warp_specialize=True,
            data_partition_factor=DATA_PARTITION_FACTOR,
            smem_alloc_algo=SMEM_ALLOC_ALGO,
            separate_epilogue_store=SEPARATE_EPILOGUE_STORE,
    ):
        offs_k = k * BLOCK_SIZE_K
        a = a_desc.load([offs_am, offs_k])
        b = b_desc.load([offs_bn, offs_k])
        accumulator = tl.dot(a, b.T, accumulator)

    c_desc.store([offs_cm, offs_cn], accumulator.to(dtype))
Persistent GEMM (tile-loop WS)

Warp-specialize the outer persistent loop. Inner K-loop uses plain range(). Based on matmul_kernel_tma_persistent_ws in same file, lines 102-167.

python
"""
Persistent GEMM with AutoWS (tile-loop warp specialization).

Usage:
    TRITON_USE_META_WS=1 python my_persistent_gemm.py
"""

@triton.jit
def matmul_persistent_ws(a_desc, b_desc, c_desc, M, N, K,
                         BLOCK_SIZE_M: tl.constexpr, BLOCK_SIZE_N: tl.constexpr,
                         BLOCK_SIZE_K: tl.constexpr, NUM_SMS: tl.constexpr,
                         DATA_PARTITION_FACTOR: tl.constexpr,
                         SMEM_ALLOC_ALGO: tl.constexpr,
                         SEPARATE_EPILOGUE_STORE: tl.constexpr, ...):
    start_pid = tl.program_id(axis=0)
    num_tiles = tl.cdiv(M, BLOCK_SIZE_M) * tl.cdiv(N, BLOCK_SIZE_N)
    k_tiles = tl.cdiv(K, BLOCK_SIZE_K)

    for tile_id in tl.range(
            start_pid, num_tiles, NUM_SMS,
            warp_specialize=True,                           # on the OUTER loop
            data_partition_factor=DATA_PARTITION_FACTOR,
            smem_alloc_algo=SMEM_ALLOC_ALGO,
            separate_epilogue_store=SEPARATE_EPILOGUE_STORE,
    ):
        # ... compute pid_m, pid_n from tile_id ...
        accumulator = tl.zeros((BLOCK_SIZE_M, BLOCK_SIZE_N), dtype=tl.float32)
        for ki in range(k_tiles):                           # plain range()
            a = a_desc.load([offs_am, ki * BLOCK_SIZE_K])
            b = b_desc.load([offs_bn, ki * BLOCK_SIZE_K])
            accumulator = tl.dot(a, b.T, accumulator)

        c_desc.store([offs_am, offs_bn], accumulator.to(dtype))
Flash Attention (inner-loop WS)

Warp-specialize the KV-iteration loop with partition scheduling hints. Based on python/tutorials/fused-attention-ws-device-tma-hopper-or-blackwell.py lines 150-155.

python
for start_n in tl.range(
        lo, hi, BLOCK_N,
        warp_specialize=warp_specialize,
        merge_epilogue=True,
        merge_correction=True,
        smem_alloc_algo=1,
        data_partition_factor=DP_FACTOR,
):
    # TMA descriptor loads for K and V
    k = k_desc.load([start_n, offs_k])
    v = v_desc.load([start_n, offs_d])
    # QK dot product
    qk = tl.dot(q, k)
    # ... softmax ...
    # PV dot product
    acc = tl.dot(p.to(dtype), v, acc)

Test & Launch Boilerplate

Correctness tests should use triton.knobs.nvidia.use_meta_ws = True (not the env var) inside a scope() block to avoid state leakage between test cases.

Based on test_tutorial09_matmul_tma_warp_specialize in python/test/unit/language/test_tutorial09_warp_specialization.py lines 416-492.

python
import torch
import triton
from triton.tools.tensor_descriptor import TensorDescriptor

def test_my_kernel():
    with triton.knobs.nvidia.scope():
        triton.knobs.nvidia.use_meta_ws = True

        M, N, K = 8192, 8192, 1024
        BLOCK_M, BLOCK_N, BLOCK_K = 128, 128, 64
        dtype = torch.float16

        torch.manual_seed(42)
        A = torch.randn((M, K), dtype=dtype, device="cuda")
        B = torch.randn((N, K), dtype=dtype, device="cuda")
        C = torch.empty((M, N), dtype=dtype, device="cuda")

        # TMA requires a custom allocator
        def alloc_fn(size, align, stream):
            return torch.empty(size, dtype=torch.int8, device="cuda")
        triton.set_allocator(alloc_fn)

        a_desc = TensorDescriptor(A, A.shape, A.stride(), [BLOCK_M, BLOCK_K])
        b_desc = TensorDescriptor(B, B.shape, B.stride(), [BLOCK_N, BLOCK_K])
        c_desc = TensorDescriptor(C, C.shape, C.stride(), [BLOCK_M, BLOCK_N])

        grid = lambda META: (triton.cdiv(M, META["BLOCK_SIZE_M"])
                           * triton.cdiv(N, META["BLOCK_SIZE_N"]),)

        # Launch — capture handle to inspect IR
        kernel = matmul_kernel_ws[grid](
            a_desc, b_desc, c_desc, M, N, K,
            BLOCK_SIZE_M=BLOCK_M, BLOCK_SIZE_N=BLOCK_N, BLOCK_SIZE_K=BLOCK_K,
            DATA_PARTITION_FACTOR=1, SMEM_ALLOC_ALGO=0,
            SEPARATE_EPILOGUE_STORE=False,
            num_stages=3, num_warps=4,
        )

        # 1. Verify WS was applied
        ttgir = kernel.asm["ttgir"]
        assert "ttg.warp_specialize" in ttgir

        # 2. Verify correct HW instructions (pick one per arch)
        # Blackwell: assert "ttng.tc_gen5_mma" in ttgir
        # Hopper:    assert "ttng.warp_group_dot" in ttgir
        assert "ttng.async_tma_copy_global_to_local" in ttgir

        # 3. Compare against reference
        ref = torch.matmul(A.float(), B.T.float()).to(dtype)
        torch.testing.assert_close(ref, C, atol=0.03, rtol=0.03)

Verifying AutoWS is Working

  1. IR check: kernel.asm["ttgir"] must contain "ttg.warp_specialize" — confirms WS was applied.

  2. MMA check: Look for "ttng.tc_gen5_mma" (Blackwell) or "ttng.warp_group_dot" (Hopper) — confirms tensor core usage.

  3. TMA check: Look for "ttng.async_tma_copy_global_to_local" — confirms async TMA copies in the producer partition.

  4. Partition check: Set MLIR_ENABLE_DUMP=1 and look for ttg.partition = array<i32: N> attributes in the IR after PartitionSchedulingMeta. This shows how ops were assigned to partitions.

  5. Full IR dump: Set TRITON_KERNEL_DUMP=<kernel_name> + TRITON_ALWAYS_COMPILE=1 to dump IR at each compilation stage. See ir-debugging skill for details.

  6. AutoWS vs TLX comparison:

    bash
    TRITON_USE_META_WS=1 python python/tutorials/test_hopper_fwd_autows_vs_tlx.py

ttg.warp_specialize is necessary, not sufficient. Its presence or count alone does not prove a correct WS kernel — an elided epilogue (Key Authoring Rule 5) leaves the op in the IR while the stores are gone. Prefer the named Meta partition list as the reliable signal: a "load" / "gemm" / "computation" set, plus a dedicated "epilogue" partition whenever the kernel has a post-loop epilogue.


2-CTA (Multi-CTA) with AutoWS

2-CTA allows two CTAs in a cluster to cooperatively execute a single MMA, doubling the N dimension of the output tile. This is a Blackwell-only, Meta WS-only feature.

Show full SKILL.md (902 more words)Show less
Requirements
  1. ctas_per_cga=(2, 1, 1) — pass this at kernel launch time (not cluster_dims or num_ctas). ctas_per_cga is the correct way to enable 2-CTA because it bypasses PlanCTA's unreliable CTASplitNum encoding by forcing num_ctas=1 internally, then using Transform2CTALoads + Insert2CTASync for B-operand splitting and cross-CTA synchronization.

  2. two_ctas=True on tl.dot() — tells the compiler this dot product should use 2-CTA MMA. The compiler automatically splits the B load across CTAs and inserts cross-CTA barriers.

  3. TRITON_USE_META_WS=1 — 2-CTA with WS is only supported by Meta's WS pipeline. Upstream OAI WS does not support cluster_dims >= 2.

  4. num_stages=1 — current 2-CTA implementations use 1 pipeline stage.

  5. Grid M dimension must be >= 2 — the grid must launch at least 2 CTAs in the cluster dimension: grid = (max(triton.cdiv(M, BLOCK_M), 2), ...).

Kernel Pattern
python
"""
2-CTA GEMM with AutoWS.

Usage:
    TRITON_USE_META_WS=1 python my_2cta_gemm.py
"""

@triton.jit
def matmul_2cta_ws_kernel(a_ptr, b_ptr, c_ptr, M, N, K,
                          stride_am, stride_ak, stride_bk, stride_bn,
                          stride_cm, stride_cn,
                          BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr,
                          BLOCK_K: tl.constexpr):
    pid_m = tl.program_id(0)
    pid_n = tl.program_id(1)
    offs_am = pid_m * BLOCK_M
    offs_bn = pid_n * BLOCK_N

    a_desc = tl.make_tensor_descriptor(
        a_ptr, shape=[M, K], strides=[stride_am, stride_ak],
        block_shape=[BLOCK_M, BLOCK_K])
    b_desc = tl.make_tensor_descriptor(
        b_ptr, shape=[K, N], strides=[stride_bk, stride_bn],
        block_shape=[BLOCK_K, BLOCK_N])
    c_desc = tl.make_tensor_descriptor(
        c_ptr, shape=[M, N], strides=[stride_cm, stride_cn],
        block_shape=[BLOCK_M, BLOCK_N])

    accumulator = tl.zeros((BLOCK_M, BLOCK_N), dtype=tl.float32)
    k_tiles = tl.cdiv(K, BLOCK_K)

    for k in tl.range(0, k_tiles, warp_specialize=True):
        offs_k = k * BLOCK_K
        a = a_desc.load([offs_am, offs_k])
        b = b_desc.load([offs_k, offs_bn])
        accumulator = tl.dot(a, b, accumulator, two_ctas=True)  # <-- 2-CTA MMA

    c_desc.store([offs_am, offs_bn], accumulator.to(tl.float16))
Launch Pattern
python
grid = (max(triton.cdiv(M, BLOCK_M), 2), triton.cdiv(N, BLOCK_N))

matmul_2cta_ws_kernel[grid](
    a, b, c, M, N, K,
    a.stride(0), a.stride(1), b.stride(0), b.stride(1),
    c.stride(0), c.stride(1),
    BLOCK_M=128, BLOCK_N=128, BLOCK_K=64,
    num_stages=1,
    ctas_per_cga=(2, 1, 1),     # <-- enables 2-CTA cluster
)
What the compiler does

When ctas_per_cga is set with two_ctas=True on tl.dot():

  1. Transform2CTALoads splits the B-operand load: each CTA loads half of BLOCK_N ([BLOCK_K, BLOCK_N/2]), offset by cluster_cta_id * BLOCK_N/2
  2. Insert2CTASync inserts cross-CTA barriers before the 2-CTA MMA using the "arrive remote, wait local" pattern via mapa instructions
  3. Both CTAs issue the MMA cooperatively
Reference files
  • 2-CTA AutoWS test: third_party/tlx/tutorials/blackwell-triton-addmm-2cta_test.py
  • TLX 2-CTA GEMM (manual WS): third_party/tlx/tutorials/blackwell_gemm_2cta.py
  • Design doc: docs/design/2cta-autoWS-sync.md
  • Transform2CTALoads: third_party/nvidia/hopper/lib/Transforms/Transform2CTALoads.cpp
  • Insert2CTASync: third_party/nvidia/hopper/lib/Transforms/Insert2CTASync.cpp

Restrictions (When WS Bails Out)

If any of these conditions are violated, the compiler silently strips WS annotations and the kernel runs without specialization.

  • Minimum 4 warps — num_warps >= 4 required (WarpSpecialization.cpp:148-153)
  • No else blocks — scf.if with non-trivial else blocks not supported (WarpSpecialization.cpp:156-170)
  • Max 16 total warps — if estimated warp budget exceeds 16, WS is stripped (PartitionSchedulingMeta.cpp:2664-2698)
  • No distance > 1 loop-carried deps (ScheduleLoops.cpp:40-41)
  • No outer loops for pipelining eligibility (ScheduleLoops.cpp:42-43)
  • No barriers, asserts, or prints in the WS loop body (ScheduleLoops.cpp:44-47)
  • Register alignment — minRegAutoWS and maxRegAutoWS must be divisible by 8 (compiler.py:140-142)
  • 2-CTA + upstream WS not supported — only Meta's WS supports cluster_dims >= 2 (compiler.py:703-706)
  • flatten=True skips WS — the kernel runs but WS is not applied
  • data_partition_factor != 1 requires sufficient BLOCK_SIZE_M (256 for Blackwell dp=2, 128 for Hopper dp=2)
  • Pointer-typed tensors should not be cross-partition

OSS Triton Fallback

The basic tl.range(warp_specialize=True) syntax works with both Meta WS and upstream OAI WS. The difference is entirely which compiler passes run, controlled by TRITON_USE_META_WS:

  • Blackwell: upstream uses add_warp_specialize; Meta uses add_partition_scheduling_meta + add_hopper_warpspec
  • Hopper: upstream uses add_hopper_warpspec only (internal doTaskPartition); Meta runs the full pipeline

Meta WS-specific features do NOT work with OSS Triton. The following kwargs and options are consumed only by Meta's compiler passes. They do not exist in OSS Triton's tl.range() signature — passing them will cause errors, not silent no-ops. If the kernel must run on both, use completely separate code paths gated by tl.constexpr:

  • Partition scheduling kwargs: merge_epilogue, merge_correction, merge_epilogue_to_computation, separate_epilogue_store
  • Memory allocation kwargs: smem_alloc_algo, tmem_alloc_algo, smem_budget, smem_circular_reuse
  • Register budget options: minRegAutoWS, maxRegAutoWS, pingpongAutoWS
  • 2-CTA / multi-CTA: multi_cta=True and cluster_dims >= 2 with WS
  • early_tma_store_lowering
Dual-mode kernel pattern

Because these kwargs do not exist in OSS Triton's tl.range(), you cannot conditionally pass them (e.g., smem_alloc_algo=1 if X else None). You must use completely separate tl.range() calls:

python
@triton.jit
def _kernel_body(a_desc, b_desc, c_desc, ...):
    # ... shared load/dot/store logic ...

@triton.jit
def my_kernel(..., USE_META_WS: tl.constexpr):
    if USE_META_WS:
        for tile_id in tl.range(
                start_pid, num_tiles, NUM_SMS,
                warp_specialize=True,
                separate_epilogue_store=True,
                smem_alloc_algo=1,
                merge_epilogue=True,
        ):
            _kernel_body(...)
    else:
        for tile_id in tl.range(
                start_pid, num_tiles, NUM_SMS,
                warp_specialize=True,
        ):
            _kernel_body(...)

Exhaustive Reference

All tl.range() kwargs (from python/triton/language/core.py)

This is the complete list of every kwarg accepted by tl.range(). Items marked (Meta only) do not exist in OSS Triton and require separate code paths.

KwargTypeDefaultAvailable in OSSDescription
num_stagesint/NoneNoneYesPipeline depth override at the loop level
loop_unroll_factorint/NoneNoneYesLoop unroll factor
flattenboolFalseYesLoop flattening for persistent kernels. True currently skips WS
warp_specializeboolFalseYesEnable AutoWS on this loop
multi_ctaboolFalseMeta onlyEnable multi-CTA (2-CTA) mode
disable_licmboolFalseYesDisable loop-invariant code motion
data_partition_factorint/NoneNoneMeta onlySplit work across N data partitions
disallow_acc_multi_bufferboolFalseMeta onlyPrevent multi-buffering of accumulators
merge_epilogueboolFalseMeta onlyMerge epilogue into computation/correction/reduction partition
merge_epilogue_to_computationboolFalseMeta onlyMerge epilogue directly to computation partition
merge_correctionboolFalseMeta onlyMerge softmax correction into computation partition
separate_epilogue_storeboolFalseMeta onlySeparate epilogue store into its own 1-warp partition
tmem_alloc_algoint/NoneNoneMeta onlyTMEM allocation strategy (Blackwell only)
smem_alloc_algoint/NoneNoneMeta onlySMEM allocation strategy (0 or 1)
smem_budgetint/NoneNoneMeta onlyOverride SMEM budget in bytes
smem_circular_reusebool/NoneNoneMeta onlyEnable circular reuse of SMEM buffers
All AutoWS-relevant environment variables (from python/triton/knobs.py)
Env VarKnobTypeDefaultDescription
TRITON_USE_META_WSknobs.nvidia.use_meta_wsboolFalseMaster switch: Meta WS vs upstream OAI WS
TRITON_DISABLE_WSBARRIER_REORDERknobs.nvidia.disable_wsbarrier_reorderboolFalseDisable WS barrier reordering
TRITON_ENABLE_INTERLEAVE_TMEMknobs.nvidia.enable_interleave_tmemboolTrueInterleave TMEM pass (Blackwell)
TRITON_DUMP_PTXAS_LOGknobs.nvidia.dump_ptxas_logboolFalsePrint ptxas verbose output (register usage)
MLIR_ENABLE_DUMP—boolFalseDump MLIR IR after each pass (for inspecting partitions)
TRITON_KERNEL_DUMP—strunsetDump IR at each stage for the named kernel
TRITON_ALWAYS_COMPILEknobs.compilation.always_compileboolFalseForce recompilation (useful with IR dumps)
All AutoWS-relevant JIT-level options (from CUDAOptions)
OptionTypeDefaultDescription
num_warpsint4Total warps per CTA. Must be >= 4 and power of 2 for WS
num_stagesint3Pipeline depth / multi-buffer count
minRegAutoWSint24Registers for non-tensor partitions. Must be divisible by 8
maxRegAutoWSint/NoneNoneRegisters for tensor partitions. Must be divisible by 8
pingpongAutoWSboolFalsePing-pong barriers between two consumer partitions
early_tma_store_loweringboolFalseLower TMA stores before partition scheduling

Reference Files

  • tl.range definition: python/triton/language/core.py (lines 3454-3484)
  • Knobs: python/triton/knobs.py (line 516)
  • Backend options: third_party/nvidia/backend/compiler.py (lines 145-180)
  • Compiler pipeline: third_party/nvidia/backend/compiler.py (lines 659-716)
  • GEMM test: python/test/unit/language/test_tutorial09_warp_specialization.py
  • AddMM test: python/test/unit/language/test_autows_addmm.py
  • FA test: third_party/tlx/tutorials/testing/test_correctness_autows.py
  • FA kernel: third_party/tlx/tutorials/fused_attention_ws_device_tma.py
  • FA kernel (DP): third_party/tlx/tutorials/fused_attention_ws_device_tma_dp.py
  • AutoWS vs TLX: python/tutorials/test_hopper_fwd_autows_vs_tlx.py
  • LIT tests: test/Hopper/WarpSpecialization/

© facebookexperimental, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .claude/skills/autows-authoring of facebookexperimental/triton.

Open the folder on GitHubat commit 6f3dd70

Compare with similar skills

Autows Authoring next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Autows Authoring compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Autows Authoring this skillfacebookexperimental/triton201—~7.1kAutomated safety check: PassMIT
Debug Distributed Hangsgl-project/sglang37k2 repos~2.4kAutomated safety check: PassApache-2.0
CUTLASS FMHA Incremental Rebuildmicrosoft/onnxruntime22k—~1.3kAutomated safety check: PassMIT
Cudatechnillogue/ptx-isa-markdown229—~2.5kAutomated safety check: PassNone
Fla Triton To Gluonfla-org/flash-linear-attention5.8k—~1.6kAutomated safety check: PassMIT
Torch Profiler Layer TrackBBuf/AI-Infra-Auto-Driven-SKILLS938—~2kAutomated safety check: PassNone

Similar skills

  • Debug Distributed Hang

    sgl-project/sglang

    Debug hanging issues in SGLang distributed inference (TP/PP/DP/EP).

    37k GitHub starsUsed in 2 repos~2.4k tokens
    DevelopmentAuto-check passed
  • Official

    Explains why editing CUTLASS fused-MHA headers in ONNX Runtime can leave stale CUDA kernels after an incremental build, and how to force and verify a real rebuild.

    22k GitHub stars~1.3k tokensUpdated today
    DevelopmentAuto-check passed
  • Cuda

    technillogue/ptx-isa-markdown

    CUDA kernel development, debugging, and performance optimization for Claude Code.

    229 GitHub stars~2.5k tokensUpdated 9 mo ago
    DevelopmentAuto-check passed
  • Fla Triton To Gluon

    fla-org/flash-linear-attention

    Port an FLA Triton kernel to Gluon when explicit layouts, asynchronous transfers, or scheduling can address a measured bottleneck.

    5.8k GitHub stars~1.6k tokensUpdated today
    DevelopmentAuto-check passed
  • Torch Profiler Layer Track

    BBuf/AI-Infra-Auto-Driven-SKILLS

    Adds verified layer guides such as L0 and L1 and compact GPU lanes to an existing Torch Profiler Chrome trace, changing how it looks but not how it ran.

    938 GitHub stars~2k tokensUpdated 5 days ago
    DevelopmentAuto-check passed
  • 3dgs Code Reviewer

    jaccen/Awesome-Gaussian-Skills

    Review 3DGS implementation code for correctness, performance bugs, and best practices.

    161 GitHub stars~2.9k tokensUpdated yesterday
    DevelopmentAuto-check passed

More from facebookexperimental/triton

All 18 skills in this repo
  • Amd Att Trace

    facebookexperimental/triton

    Official

    Collect, validate, package, and inspect rocprofv3 Advanced Thread Trace bundles for AMD GPU kernels.

    201 GitHub stars~733 tokensUpdated today
    Auto-check passed
  • Ir Override Ablation

    facebookexperimental/triton

    Official

    Design and run Triton TTGIR debugging ablations using iroverride.

    201 GitHub stars~978 tokensUpdated today
    Auto-check passed
  • Tlx Kernel Optimization Agent

    facebookexperimental/triton

    Official

    Execute the TLX Kernel Optimization Agent CLI on a Triton or TLX kernel.

    201 GitHub stars~3.5k tokensUpdated today
    Auto-check passed
  • Compute Sanitizer

    facebookexperimental/triton

    Official

    Run NVIDIA compute-sanitizer (memcheck, racecheck, initcheck, synccheck) against a Triton/TLX kernel to find runtime memory and synchronization bugs.

    201 GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • Debug Failing GPU

    facebookexperimental/triton

    Official

    Recover from GPU-busy / GPU-unavailable failures. An agent skill from facebookexperimental/triton.

    201 GitHub stars~709 tokensUpdated today
    Auto-check passed
  • Ir Debugging

    facebookexperimental/triton

    Official

    Debug Triton compilation by dumping IR at each stage (TTIR, TTGIR, LLVM, PTX).

    201 GitHub stars~644 tokensUpdated today
    Auto-check passed

Questions about Autows Authoring

What does Autows Authoring do?

Author Triton kernels with automatic warp specialization (AutoWS). Autows Authoring is an agent skill from facebookexperimental/triton, published by the product's own GitHub organization. Author Triton kernels with automatic warp specialization (AutoWS).

When should I use Autows Authoring?

Autows Authoring fits situations like: writing new AutoWS kernels; adding warpspecialize=True to tl.range loops; choosing tl.range kwargs and JIT options; debugging why WS was not applied.

How do I install Autows Authoring in Claude Code?

Run `npx skills add facebookexperimental/triton --skill autows-authoring -a claude-code`. Or copy the skill folder (.claude/skills/autows-authoring in facebookexperimental/triton) into .claude/skills/autows-authoring in your project. Claude Code loads it when a task matches its description.

How do I install Autows Authoring in Codex?

Run `npx skills add facebookexperimental/triton --skill autows-authoring -a codex`. Or copy the skill folder (.claude/skills/autows-authoring in facebookexperimental/triton) into .agents/skills/autows-authoring in your project. Codex loads it when a task matches its description.

Can I use Autows Authoring in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add facebookexperimental/triton --skill autows-authoring -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/autows-authoring, .gemini/skills/autows-authoring, .github/skills/autows-authoring and .opencode/skills/autows-authoring in your project.

What does Autows Authoring need to run?

Going by SKILL.md and its folder, Autows Authoring needs the command-line tools its instructions call (python). Our summary lists: Python 3.

Does Autows Authoring access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Autows Authoring safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Autows Authoring use?

Autows Authoring is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Autows Authoring use?

About 7.1k tokens (SKILL.md is roughly 28k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Autows Authoring?

Skills that share tags, products or a category with Autows Authoring: Debug Distributed Hang (sgl-project/sglang, 37k stars), CUTLASS FMHA Incremental Rebuild (microsoft/onnxruntime, 22k stars), Cuda (technillogue/ptx-isa-markdown, 229 stars) and Fla Triton To Gluon (fla-org/flash-linear-attention, 5.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Autows Authoring?

facebookexperimental (a GitHub organization, an official publisher) maintains it in facebookexperimental/triton, which has 201 GitHub stars. The repository holds 18 skills in this directory. The repository was last updated on October 10, 2026.

Source: facebookexperimental/triton on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.