Files
derek.holloway 7502bf64a4
CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
Flatten subprojects into a single base monorepo
2026-09-02 16:34:47 -07:00
..

rocke_engine — pybind11 binding for the C++ Cpp engine

This directory is the binding layer of the dual-backend path. It builds a Python extension module, rocke_engine, that wraps the prebuilt C++ engine archive (librocke_core.a) and exposes its public C API to Python.

It is additive and isolated: it adds only new files under bindings/, links the engine archive read-only, and #includes the public headers in ../include/rocke/. It does not modify the engine src//include/, the main CMakeLists.txt, or the Python rocke package.

Module API

The first template family is the universal GEMM. The Python spec argument is a dict carrying the UniversalGemmSpec fields. Keys may be flat (tile_m, pipeline, dtype_a, …) or nested (tile={...}, trait={...}, data={...}); every field defaults to the C engine default, so a minimal dict {name, tile_m, tile_n, tile_k, warp_m, warp_n} works.

import rocke_engine

spec = dict(
    name="test1",
    tile_m=128, tile_n=128, tile_k=32,
    warp_m=2, warp_n=2, warp_k=1,
    warp_tile_m=16, warp_tile_n=16, warp_tile_k=16,
    pipeline="compv3", epilogue="default",
    dtype_a="fp16", dtype_b="fp16", dtype_c="fp16", dtype_acc="fp32",
    wave_size=64, block_size=256, batched=False,
)

ll  = rocke_engine.gemm_lower_llvm(spec, arch="gfx950")    # -> str  (AMDGPU .ll)
ir  = rocke_engine.gemm_serialize_ir(spec, arch="gfx950")  # -> str  (ck.dsl.ir/v1)
ds  = rocke_engine.gemm_verify(spec, arch="gfx950")        # -> list[str] (diagnostics; [] == well-formed)
ok, why = rocke_engine.gemm_is_valid(spec, arch="gfx950")  # -> (bool, str)
name    = rocke_engine.gemm_kernel_name(spec)              # -> str
function C engine entry point returns
gemm_lower_llvm(spec, arch) rocke_gemm_universal_lower_to_llvm (build + lower) .ll text
gemm_serialize_ir(spec, arch) rocke_build_universal_gemm_new + rocke_ir_serialize ck.dsl.ir/v1 text
gemm_verify(spec, arch) rocke_build_universal_gemm_new + rocke_verify list[str]
gemm_is_valid(spec, arch) rocke_gemm_universal_is_valid_spec (bool, reason)
gemm_kernel_name(spec) rocke_gemm_universal_kernel_name str

arch defaults to "gfx950".

Error model

The engine uses a sticky-error IRBuilder. On a build/lower failure (e.g. an invalid spec rejected by the validity gate) the binding raises a Python RuntimeError carrying the rocke_ir_builder_error() / status text. Arena and builder lifetime are managed inside each call (built, used, then rocke_ir_builder_free'd before returning); the char* results malloc'd by the engine are copied into a std::string and free'd.

Build

  1. Build the engine archive (read-only; never modify the engine):

    # run from the rocke/platform/ root; the top-level CMakeLists builds the rocke_core archive
    cmake -S . -B /tmp/rocke_pybind/engine -DCMAKE_BUILD_TYPE=Release
    cmake --build /tmp/rocke_pybind/engine --target rocke_core -j"$(nproc)"
    # -> /tmp/rocke_pybind/engine/librocke_core.a
    
  2. Build the extension (its own CMake; points at the archive + headers + a python that has pybind11):

    cmake -S cpp/bindings -B /tmp/rocke_pybind/build \
      -DCMAKE_BUILD_TYPE=Release \
      -DROCKE_ENGINE_ARCHIVE=/tmp/rocke_pybind/engine/librocke_core.a \
      -Dpybind11_DIR="$(python -m pybind11 --cmakedir)" \
      -DPYTHON_EXECUTABLE="$(which python)"
    cmake --build /tmp/rocke_pybind/build -j"$(nproc)"
    # -> /tmp/rocke_pybind/build/rocke_engine.cpython-3XX-*.so
    

    Use a python environment that has pybind11 (>= 3.0) installed so that find_package(pybind11) resolves.

    The engine compiles as C++20; the binding sets CMAKE_CXX_STANDARD 20. The archive's symbols are reached through the extern "C" public headers, so it links cleanly (target_link_libraries(... librocke_core.a m)).

Consistency proof

/tmp/rocke_pybind/prove_parity.py drives all the GEMM configs from tests/instances/parity/gemm_emit.py through rocke_engine and compares to the Python engine (lower_kernel_to_llvm(build_universal_gemm(spec)) and ir_serialize.serialize). Because the binding drives the same C++ engine the differential harness already validates, valid configs are byte-identical (sha equal) and invalid configs are rejected identically by both engines.

cfg   LL                  IR
test1 byte-identical       byte-identical
test2 both reject (LDS budget 196608 > 163840 cap on gfx950)
test3 both reject (unsupported bf16 warp_tile (32,32,8) on gfx950)
test4 byte-identical       byte-identical
test5 byte-identical       byte-identical
test6 byte-identical       byte-identical
test7 both reject (unsupported fp16 warp_tile (32,32,32) on gfx950)

How this becomes the ROCKE_BACKEND=cpp backend

This module is the engine side of the dual-backend switch, and cpp is now the default: rocke.core.backend routes lowering through this engine. For a Python-authored kernel it serializes the IR and calls the family-agnostic rocke_engine.lower_serialized_ir(...); for cataloged families the per-family <fam>_lower_llvm / _serialize_ir / _verify entry points are used. If rocke_engine isn't importable, the chokepoint auto-falls back to the native Python lowerer (byte-identical) and records why. Select explicitly with ROCKE_BACKEND=python|cpp|both.

Environment flags: this harness uses ROCKE_PARITY_BUILD (the .so dir) and ROCKE_PARITY_EMIT (the prebuilt-emitter dir) — point both at the same fresh build. The backend/flavor flags are ROCKE_BACKEND, ROCKE_LLVM_FLAVOR, ROCKE_CPP_STRICT. Full list: ../../dsl_docs/reference/env_flags.md.

Parity rule: every optimization in the Python engine must have its C++ twin, proven byte-identical — see ../../dsl_docs/development/engine_parity.md.