Arch spec static polymorphism for codegen
Skill kjuhwa/skills-hub/skills/jit-compilation/arch-spec-static-polymorphism-for-codegen
Use a templated `get_best_config<ArchSpec>(desc)` where each architecture (SM90, SM100, etc.) is a plain struct full of `static` methods, so the compiler inlines the arch-specific heuristic with zero virtual-call overhead.From its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill arch-spec-static-polymorphism-for-codegenAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
4.4 KB, 883 tokens by cl100k_base, as published. Nobody here has run it
ArchSpec Static Polymorphism For Heuristic Dispatch
When to use
You're maintaining a heuristic engine that picks GEMM configs for more than one GPU architecture (Hopper vs Blackwell vs future SMs). You want:
- A single orchestrator function (
get_best_config) that's written once. - Zero runtime vtable cost on the hot path.
- The ability to add a new arch by adding a file, not touching the orchestrator.
An abstract base class with virtuals costs a dispatch per call and tangles arch-specific constants into a base that doesn't actually share them. This skill inverts that: write each arch as an independent struct of static methods, then make the orchestrator a template.
Steps
- Declare the arch struct in its own header with only static methods and
static constexprmembers:struct SM90ArchSpec { static constexpr int smem_capacity = 232448; static std::vector<Layout> get_layout_candidates(const GemmDesc&); static StorageConfig get_storage_config(const GemmDesc&, const Layout&); static PipelineConfig get_pipeline_config(const GemmDesc&, const Layout&, const StorageConfig&); static LaunchConfig get_launch_config(const GemmDesc&, const Layout&); static LayoutInfo get_layout_info(const GemmDesc&, const Layout&); static bool compare(const LayoutInfo&, const LayoutInfo&); }; - Orchestrator is a free template function:
template <typename ArchSpec> GemmConfig get_best_config(const GemmDesc& desc) { const auto cands = ArchSpec::get_layout_candidates(desc); auto best = cands[0]; for (size_t i = 1; i < cands.size(); ++i) if (ArchSpec::compare(...)) best = cands[i]; // infer storage/pipeline/launch configs } - Dispatch at the API boundary, not inside the loop:
return arch_major == 9 ? get_best_config<SM90ArchSpec>(desc) : arch_major == 10 ? get_best_config<SM100ArchSpec>(desc) : /* throw */; - Comparators can be arch-specific. SM90 uses a cycle-model comparator (
num_cycleslow is best). SM100 uses lexicographic comparisons on wave count / cluster size / block dims. Both honor the samebool compare(a, b)contract without sharing implementation. - Shared struct definitions live in
config.hpp—GemmDesc,Layout,LayoutInfo, etc. — so every arch agrees on the data types but not the scoring. - No virtual methods, no inheritance, no
dynamic_cast. Each arch's constants (smem_capacity, MMA shapes, TMEM limits) arestatic constexprvisible at the callsite — the compiler can fold them into constants.
Evidence (from DeepGEMM)
csrc/jit_kernels/heuristics/common.hpp:13-52: theget_best_config<ArchSpec>template orchestrator.csrc/jit_kernels/heuristics/sm90.hpp:13-244:SM90ArchSpecwith cycle-model comparator using modeled L1/L2 bandwidth.csrc/jit_kernels/heuristics/sm100.hpp:14-267:SM100ArchSpecwith lexicographic comparator on wave count / cluster / block dims.
Counter / Caveats
- Not suitable when you need a runtime-configurable third arch — the dispatch must be known at compile time. If you need a plugin, add a virtual base and accept the indirection cost.
- Each arch method can diverge wildly. SM90
compareis one line (num_cycles < num_cycles). SM100compareis 25 lines of lexicographic fallbacks. The contract is "returns bool, same semantics", not "same implementation shape" — don't try to force uniformity. - Adding a new arch requires touching the API-level dispatch. This is the intentional tradeoff for zero-overhead dispatch.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.