Skip to content

feat(hip-kernel-provider): runtime-dispatch packaged gfx950 rocKE conv forward through hipDNN - #12780

Closed
aledudek wants to merge 6 commits into
developfrom
users/aledudek/gfx950-conv-ingestor-dev
Closed

aledudek wants to merge 6 commits into
developfrom
users/aledudek/gfx950-conv-ingestor-dev

Conversation

@aledudek

@aledudek aledudek commented Sep 30, 2026 •

Copy link
Copy Markdown
Contributor

ISSUE ID: AICK-2048

Replaces: #12476

Motivation

Ships rocKE-authored gfx950 forward convolutions as a hipDNN engine, hipkernel:Gfx950ConvFwd. The kernels are compiled ahead of time into the provider's kpack archive and dispatched at runtime without Python. Each problem has several candidate kernels; on first use hipDNN benchmarks them and records the fastest, and later processes reuse the recorded winner without searching again.

rocKE's gfx950 forward dispatcher returns one fixed implicit-GEMM configuration for every problem and never selects rocKE's direct depthwise kernels. Packaging both kernel families behind hipDNN's benchmarking gives per-problem selection, including between families.

Rebased onto develop including #12783 (rocKE conv kernels switched to AOT). That change gave both conv kernel families a new kernel-argument ABI, which this PR now launches with. It also introduced a store-width regression for grouped and channel-padded convolutions, which the first commit fixes (see rocKE fix below).

Technical Details

  • rocKE fix (fix(rocke): size the conv fwd cshuffle store to K/groups again, own commit, easy to split out): after feat(rocke): switch conv kernels to AOT #12783 the Python builder defaults the cshuffle store width to 8. When K/groups is not a multiple of 8, a vector store straddles the end of a group's output slab, fails its bounds check as a whole and is dropped, so those outputs are never written. Grouped, depthwise and dense convolutions are all affected; the dispatcher picks cshuffle for any even K/groups. The commit restores the default_vector_sizes(cpg, kpg) width, which the C++ engine already uses, so the two engines agree again. The byte-identity corpus had no config where the two defaults differ; a grouped config with K/groups = 12 is added to both conv parity emitters. It is red on develop and green with the fix.

  • Native engine pack (packs/Gfx950ConvFwdNative.cpp, packs/Gfx950ConvFwdGeometry.hpp): graph matcher, kernel matcher, scorer and dispatcher for 2-D forward cross-correlation, NHWC fp16/bf16 tensors, fp32 accumulation, symmetric padding.

    • Grouped convolution is supported: groups are inferred as X channels / W dimension 1, run one group per grid z slice, and size the filter buffer as K·Y·X·(C/groups).
    • Grouped pointwise (1x1, stride 1, no padding, groups > 1) is declined: rocKE's pointwise shortcut ignores the group offset.
    • Each kernel is compiled for one exact geometry; the kernel matcher requires the geometry, groups, dtype and family fields to equal the descriptor metadata. The AOT kernels still make code-shape decisions from the build-time problem, so this stays a per-shape catalog.
    • Uses the KPACK-only kernel-code overload and exports its module cache like the other packs.
  • AOT launch ABI: both families open with (A, B, D, A_bytes, B_bytes, D_bytes) and append the problem as i32 kernel arguments, in the order defined by rocke/library/kernels/common/conv_abi.py:

    • implicit GEMM appends 39: extents and conv attributes, Ho/Wo, C/groups and K/groups, the GEMM extents, packed NHWC/KYXC/NHWK strides, magic-division pairs for Ho, Wo, X and C/groups, and the tile counts num_pid_m/num_pid_n;
    • the direct depthwise kernels append 14: N, Hi, Wi, Ho, Wo, groups, total C and K, and the activation/output strides.
    • The pack computes the values the way rocKE's ConvArgs.to_launch_values does (implicitGemmKernargs, directKernargs, magicDivision); unit tests compare them with ConvArgs output.
    • The expected signature carries the argument names, which hkp_pack records from the code object. Every problem argument is a by_value i32, so only the names catch a reordering; a mismatch fails at prepare().
    • A reduction extent Y·X·C/groups at or above 2^23 is refused, as ConvArgs does, for the kernel's 24-bit address products.
  • Two kernel families in one engine, selected per problem:

    • implicit GEMM (kernel_family = 0) serves every accepted graph;
    • rocKE's direct depthwise kernels (kernel_family = 1, std and spatial variants) serve pure depthwise graphs, with their own ABI block and launch grid.
    • kernel_family is an integer engine knob; benchmarking compares both families. Without benchmarking or a record, the default direct arm ranks first.
    • Direct kernels are accepted only for groups == C == K, equal strides and padding, no dilation, odd filter extents with "same" padding (rocKE's own forward_padding_reason, mirrored natively), and floor((in - 1) / stride) == out - 1 on H and W. The last check still matters for the width of a non-square filter. Other depthwise graphs stay on implicit GEMM.
  • Builder adapter (rocke/library/builders/common/convolution_forward.py): builds either family through hkp_pack, with a build-time support predicate and hashed kernel symbols. Implicit-GEMM pipelines: mem, compv3, compv4, basic. launch_signature() / launch_values() expose the AOT launch through ConvArgs.

  • Catalog (synthetic verification shapes only): 44 requests, 118 kernels (88 implicit GEMM with tile_k 64 and 128, 30 direct), generated from IngestorGenerator/configs/gfx950_conv_fwd.yaml into the provider's shipped descriptor root src/engines/kernel_ingestor_engine/descriptors/rocKE/gfx950_conv_fwd/. Unchanged by the rebase: every spec still validates against the AOT builders and every direct entry already uses "same" padding. Workload catalogs are built outside the tree; the procedure is in docs/gfx950_conv_fwd/README.md ("Private workload catalogs").

  • Generator (IngestorGenerator/codegen): opt-in builder_default: true on KMD fields, so fields added with a default are omitted from existing entries and an extended bundle keeps its descriptors byte-identical. Feedback from the hipDNN tooling owners welcome.

  • Test registration: hkp_gfx950_conv_fwd_available() gates the census suite and the external integration target, which is routed into the gfx950 census shard, with config/hipkernel_Gfx950ConvFwd.toml and the categories YAML.

  • Tooling: mine_conv_shapes.py derives conv requests from benchmark graphs (its output stays outside the tree); benchmark_conv_integration.py checks correctness and compares against a direct rocKE launch, for either family, through the adapter's AOT launch helpers.

  • Docs: docs/gfx950_conv_fwd/ (README, graph_contract, coverage, mining), including the AOT launch contract.

Test Plan

On gfx950, from a clean build of this branch with every pack re-packed against the AOT builders, and an install of that build:

  • rocKE adapter, conv ABI and library-layering pytest; IngestorGenerator suite and launch-surface check; descriptor-packaging suite.
  • C++ unit (hip_kernel_provider_tests) and census (hip_kernel_provider_census_tests via CTest from the install tree).
  • Descriptor gates: hipdnn_validate_descriptors (both shipped engines), hkp_desk_check --mode full, verify_variant_sets --mode full.
  • Provider GPU integration (hip_kernel_provider_integration_tests): every catalog variant against the CPU reference, every direct arm, cross-family benchmarking with winner reuse, and depthwise graphs outside the direct guard.
  • Engine-pinned integration bundles (hipdnn_integration_tests --test-engine hipkernel:Gfx950ConvFwd --reference-executor gpu --fail-on-unsupported): Smoke, Spatial and Depthwise.
  • Conv external-integration CTest target from the install tree.
  • rocKE merge gates against a develop control: build, golden, conv byte-identity at llvm20 and llvm22; rocKE conv forward GPU correctness.

Test Result

  • rocKE: adapter 176 passed; with conv ABI and layering, 267 passed.
  • IngestorGenerator: 953 passed, 24 skipped. Launch-surface check passed (14 surfaces).
  • Descriptor packaging: 447 passed, 1 skipped. The 52 HIP-fixture compile tests in test_hkp_pack_hip.py / test_hkp_pack_layout.py (30 failed, 22 errors) fail on the test machine because its HIP compiles pick up the distro HIP headers instead of ROCm's. This PR changes neither those fixtures nor the HIP compile path.
  • C++ unit: 978 passed, 6 skipped (they need two devices); *Gfx950ConvFwd*: 54 passed. Census (gfx950, install tree): 21/21.
  • Descriptor gates: both engines load with nothing dropped; desk check and variant sets agree on 118/118 kernels in full mode.
  • Provider GPU integration: *Gfx950ConvFwd* 133/133; whole binary 162/162.
  • Integration bundles: 34/34, 0 skipped.
  • Conv external-integration CTest target (install tree): passed.
  • rocKE gates: build, golden and conv byte-identity (llvm20 and llvm22) green, as on the develop control; the new parity config is red on develop and green here. Conv forward GPU correctness passed.

hip_kernel_provider_integration_tests needs no environment override: its main() adds the production descriptor tree through HIPDNN_DESCRIPTOR_RUNTIME_DIR alongside the test set. The categorized external suites need the TOML next to their CTest file, so they run from an install tree.

Known limitations: the shipped catalog is synthetic, so real workloads need a private catalog; depthwise 1x1 at stride 1 without padding is declined by both families; the unbenchmarked order ranks the direct family first, and benchmarking corrects it where implicit GEMM is faster.

Not addressed here (rocKE, pre-existing): for a one-element cshuffle store, the C++ engine's shared CShuffleEpilogue reads two elements from LDS where the Python engine reads one. No current byte-identity config reaches that path, and the packaged kernels are built with the Python engine. Fixing it touches an epilogue shared by every kernel family, so it is left for a separate change.

Submission Checklist

@therock-pr-bot

therock-pr-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

✅ All Checks Passed — Ready for Review

Check Status Details
📝 PR Description ✅ Pass —
⛔ Forbidden Files ✅ Pass —
🧪 Unit Test ✅ Pass —
🔎 pre-commit ✅ Pass —
🚫 Draft PR 🔜 To Be Enabled —
🚩 Feature Flag 🔜 To Be Enabled —
📊 Code Coverage 🔜 To Be Enabled —
🤖 therock-pr-bot ✅ Pass —

🎉 All checks passed! This PR is ready for review.

📖 Need help? See the Policy FAQ for details on every check and how to fix failures.

🙋 Wish to Override Policy?

@therock-pr-bot

therock-pr-bot Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

🎉 All checks passed! This PR is ready for review.

@aledudek
aledudek force-pushed the users/aledudek/gfx950-conv-ingestor-dev branch from 8e7c0db to 9fd94d4 Compare September 30, 2026 14:18
@codecov

codecov Bot commented Sep 30, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

Additional details and impacted files
@@           Coverage Diff            @@
##           develop   #12780   +/-   ##
========================================
  Coverage    72.12%   72.12%           
========================================
  Files         2869     2869           
  Lines       473609   473609           
  Branches     69870    69870           
========================================
+ Hits        341565   341570    +5     
+ Misses      108304   108302    -2     
+ Partials     23740    23737    -3     
Flag Coverage Δ *Carryforward flag
TensileLite-CPP 49.33% <ø> (ø) Carriedforward from dd76b08
TensileLite-Unit 83.30% <ø> (ø) Carriedforward from dd76b08
hipBLAS 90.62% <ø> (ø) Carriedforward from dd76b08
hipBLASLt 38.91% <ø> (ø) Carriedforward from dd76b08
hipCUB 82.68% <ø> (ø) Carriedforward from dd76b08
hipDNN 86.67% <ø> (+0.01%) ⬆️
hipFFT 43.43% <ø> (ø) Carriedforward from dd76b08
hipRAND 76.12% <ø> (ø) Carriedforward from dd76b08
hipSOLVER 68.96% <ø> (ø) Carriedforward from dd76b08
hipSPARSE 86.99% <ø> (ø) Carriedforward from dd76b08
rocBLAS 48.24% <ø> (ø) Carriedforward from dd76b08
rocFFT 51.45% <ø> (ø) Carriedforward from dd76b08
rocRAND 57.45% <ø> (ø) Carriedforward from dd76b08
rocSOLVER 76.83% <ø> (ø) Carriedforward from dd76b08
rocSPARSE 74.07% <ø> (ø) Carriedforward from dd76b08
rocThrust 93.15% <ø> (ø) Carriedforward from dd76b08

*This pull request uses carry forward flags. Click here to find out more.
see 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@aledudek
aledudek force-pushed the users/aledudek/gfx950-conv-ingestor-dev branch from 9fd94d4 to c21cf42 Compare October 1, 2026 15:41
@github-actions github-actions Bot added the rocke: platform Touches rocKE platform label Oct 1, 2026
@aledudek
aledudek force-pushed the users/aledudek/gfx950-conv-ingestor-dev branch 2 times, most recently from d7f2147 to 3a9c3e3 Compare October 2, 2026 13:47
@aledudek
aledudek marked this pull request as ready for review October 2, 2026 14:04
@aledudek
aledudek requested review from a team as code owners October 2, 2026 14:04
@aledudek
aledudek force-pushed the users/aledudek/gfx950-conv-ingestor-dev branch from 3a9c3e3 to 54717ce Compare October 6, 2026 12:23
@BradPepersAMD

Copy link
Copy Markdown
Contributor

With the AOT changes for the rocKE kernels so that the shape isn't hard-coded at compile time, the matcher in here needs to change to also be more relaxed and use the kernels for the range of what they actually can handle at runtime now.

@aledudek

aledudek commented Oct 7, 2026

Copy link
Copy Markdown
Contributor Author

With the AOT changes for the rocKE kernels so that the shape isn't hard-coded at compile time, the matcher in here needs to change to also be more relaxed and use the kernels for the range of what they actually can handle at runtime now.

Good point, thanks. Updated the matcher, it no longer requires the exact build shape. It only checks what the binary still bakes in after AOT, so each kernel is used for every shape it can run.

@cgmillette cgmillette left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR #12780 — gfx950 rocKE conv fwd as an AOT hipDNN engine (aledudek, AICK-2048) — 🟠 REJECT: sound and well-tested, but needs a careful rebase onto #12659

Prior item Status
BradPepersAMD: matcher must serve every shape the AOT kernels can run, not just the build shape 🟢 FIXED 055b1a09: matches on baked caps only (load/store width, grouped/pointwise; direct: filter/stride/pad, spatial G). Same rule as rocKE KernelCache.supports_problem
Bots: policy ✅ (AICK-2048), codecov, Math CI 🟡 Math CI SKIPPED at 055b1a09; codecov tracked +3 lines. GPU/C++ results are author-reported only
# Sev file:line Net-new finding
N1 🟠 HkpPackaging.cmake:1273 dirty vs develop #12659 (rocKE optional, default OFF): 3 conflicts. The auto-merged hkp_gfx950_conv_fwd_available() still calls _hkp_root_declares_engine_for_arch, which #12659 deleted → "Unknown CMake command" on every gfx950 rocKE-ON configure. Port to develop's probe form (HKP_PACK_SHIPPED_ENGINES_product).
N2 🟠 integration_tests/CMakeLists.txt:85, test_desk_check_invariants.py:426 Same rebase, 2 silent test breaks. (a) Conv suite compiled ungated (develop gates attention's with hkp_product_offers_engine); it skips only non-gfx950 (IntegrationGpuGfx950ConvFwd.cpp:395) and ASSERTs the engine is offered (:411) → red on gfx950 with rocKE OFF. (b) dtype-premise fix must move to tests/rocke/test_desk_check_rocke_corpus.py:297, which still asserts ("bf16","BF16"); conv bundle is fp16/fp16.
N3 🟡 Gfx950ConvFwdNative.cpp:446-462 isDefaultDirectArm keys on the kernel's build G, not the graph's. Post-relaxation, on a non-catalog G=32 graph the std bw4 builds for G=64/96 tie the spatial default at 4.0, while the identical G=32 build ranks 3.0. Unbenchmarked order only; test :1204 uses same-shape kernels. Use matched.problem.groups.
N4 🟡 gfx950_conv_fwd.kdp.json Relaxed matching makes the per-shape catalog mostly duplicates: 88 implicit-GEMM kernels = 24 capability classes; verified IR-identical modulo name for the 11-kernel class. Median catalog graph: 26 candidates / 4 distinct binaries (max 44/12); BenchmarkPlan times every one (1+7 runs). Follow-up: one kernel per class.
N5 🟡 PR body; coverage.md:68 Stale after 055b1a09. Body: "exact geometry", "per-shape catalog", grouped pointwise "declined". coverage.md:68: depthwise 1×1 s1 p0 "declined by both families". Head serves grouped pointwise (Native.cpp:204-207, README.md:9-10). Fix before squash.

Utility: 🟢 Positive and needed: first Python-free, runtime-dispatched rocKE conv engine in hipDNN with cross-family benchmarking. 958ea54d fixes a live develop bug (cshuffle store width 8 drops outputs when K/groups % 8 ≠ 0; config-20 IR v4i32→v2i32), so land it first. Matcher, ABI names and kernargs check out against rocKE on host (adapter 181/181). Merge after the N1/N2 rebase.


Legend: 🔴 blocking · 🟠 should-fix · 🟡 minor nit · 🟢 info/good

…s, grouped included, through hipDNN

Add hipkernel:Gfx950ConvFwd, a kernel-ingestor engine that serves 2D forward
cross-correlation on gfx950 from rocKE implicit-GEMM kernels compiled ahead of
time into the provider's kpack. Each compiled variant is specialized for one
convolution geometry; the native pack matches the hipDNN graph against the
packaged metadata exactly and launches the code object without Python.

Contract: dense channels-last FP16/BF16 storage, FP32 accumulation, symmetric
padding, groups inferred as X channels / W dimension 1 (any divisor of C and K
up to the grid-z limit, depthwise and channel-multiplier depthwise included).
Grouped pointwise (1x1, stride 1, no padding) is declined in the native
matcher, the rocKE adapter and the shape miner: rocKE's pointwise shortcut
indexes the input and output without the group offset and writes wrong
results. Launch geometry runs N-tiles over K/G with one grid z-slice per
group, and the filter byte count uses C/G so the B buffer-resource bound
matches the packed [K, Y, X, C/G] allocation.

The shipped catalog holds synthetic verification shapes only, each with
tile_k 64 and 128. Workload shapes are never committed: production catalogs
are generated from a private request list and packed from a descriptor root
outside the source tree via HIPKERNELPROVIDER_PRODUCTION_SOURCE_ROOT, as
documented in docs/gfx950_conv_fwd/README.md.

Integration follows the ingestor runbook and the gfx950_attention_dense
reference: the bundle lives in the shipped descriptor root; tests register
behind hkp_gfx950_conv_fwd_available() and route into the gfx950 census
shard; a census suite, matcher/geometry unit tests, a GPU integration test,
shared integration bundles and a provider-level external check target with
its TOML are added. The native pack uses the KPACK-only kernel-code overload
and exports its module cache. The generator config, request inventory and
tooling profile (with the specialization block dispatch_parity needs) live
under IngestorGenerator/configs; mine_conv_shapes.py and
benchmark_conv_integration.py mine requests and probe the integrated path.
The attention profile now names its bundle, since the gfx950 shard holds two.

Verified on gfx950 with the default production root: provider unit tests,
conv and attention census suites, descriptor validator (both engines), desk
check and verify_variant_sets in full mode, the conv GPU integration test and
external integration suites with grouped and depthwise cases executing,
dispatch_parity, launch_surface, the runbook placeholder gate, and the
IngestorGenerator and rocKE packaging pytest suites. Not run: the attention
GPU suites (SDPA off in this build).
…irect kernel

hipkernel:Gfx950ConvFwd served depthwise convolution only through the
implicit-GEMM kernel. With one channel per group every lane of that kernel
loads from its own cache line, so most of each memory request is discarded
and no tile, warp or pipeline choice changes the lane-to-address mapping.
rocKE's direct depthwise kernels map adjacent channels to adjacent lanes and
read each input line once. They take the same six kernel arguments as the
implicit-GEMM kernel and need no LDS or workspace, so they are packaged as a
second kernel family in the same engine.

Kernel families:
- New metadata fields kernel_family (0 implicit GEMM, 1 direct depthwise),
  direct_variant (std or spatial), block_w and block_waves. kernel_family is
  an integer engine knob, so a family can be forced; benchmarking compares
  both families. Without benchmarking, direct candidates rank above implicit
  GEMM where they apply, the default direct arm first.
- Direct kernels carry fixed placeholders for the implicit-GEMM fields. The
  native pack refuses unknown families and inconsistent field combinations,
  and launches std and spatial kernels with their own grid and block.
- The direct kernel's own symbol omits filter size, padding and stride, so
  the adapter names every direct kernel from a hash of the full spec.

Correctness guards: the direct kernels leave trailing output rows unwritten
when padding exceeds (filter - 1) / 2, and on their runtime-loop path can
write past the last output row into the next image. Both the rocKE adapter
and the native kernel matcher accept a direct kernel only when the last
output row covers the last input row (floor((in - 1) / stride) == out - 1,
for H and W), with groups == C == K, symmetric stride and padding, no
dilation, and the spatial variant only below 64 groups. Every other shape
stays on implicit GEMM, which serves it correctly. The kernels themselves
are not changed here.

Existing kernels are unchanged: the generator gains an opt-in
builder_default flag on KMD fields, so descriptors that leave the new fields
at their defaults keep their metadata. All previously shipped descriptors,
symbols and code objects are byte-identical, pinned by a test. The synthetic
catalog adds direct arms for the existing depthwise shapes and new synthetic
cases for stride 2 with odd and even heights, a partial channel tile, both
runtime-loop paths, and depthwise graphs that must stay on implicit GEMM.
benchmark_conv_integration.py discovers and forces either family.

Verified on gfx950: provider unit tests, conv and attention census suites,
descriptor validator, desk check and verify_variant_sets in full mode, the
conv GPU integration test (every direct arm against the CPU reference,
cross-family benchmarking and winner reuse, implicit-GEMM fallbacks), the
shared integration bundles including the new Depthwise bundle, the runbook
placeholder gate, launch_surface, dispatch_parity, and the IngestorGenerator,
descriptor-packaging and rocKE packaging pytest suites. Not covered:
benchmark_conv_integration.py still needs an implicit-GEMM arm for
auto/reuse runs, and the attention GPU suites (SDPA off in this build).
…v pack

The Linux superbuild runs clang-tidy with warnings as errors, and the gfx950 conv
pack and its tests tripped six checks: a negated conjunction in the epilogue rule
(readability-simplify-boolean-expr), a repeated return type
(modernize-return-braced-init-list), a redundant member initializer, a push_back in
a loop without reserve, an int multiplication widened to int64, and adjacent string
literals that clang-format produced by splitting long kernel names in the census
inventory (bugprone-suspicious-missing-comma). The census name list is now exempt
from clang-format so each kernel name stays one literal.

No behaviour change. Verified: clang-tidy with the hipDNN configuration reports
nothing in the touched files; provider unit, census and the gfx950 conv GPU
integration tests pass.
The AOT switch made the Python builder default the cshuffle store width to
8. When K/groups is not a multiple of 8, a vector store straddles the end
of a group's output slab, fails its bounds check and is dropped, so those
outputs are never written. This hits grouped, depthwise and dense convs.
Restore the default_vector_sizes(cpg, kpg) width, which the C++ engine
already uses, so the two engines agree again.

Add a grouped config with K/groups = 12 to both conv parity emitters; the
byte-identity gate had no case where the two defaults differ.
…OT conv ABI

rocKE's conv kernels now take the problem as kernel arguments: implicit
GEMM appends 39 i32s and the direct depthwise kernels 14 to the six leading
arguments. The native pack computes them as ConvArgs does (extents, packed
strides, magic-division pairs, tile counts) and checks a named signature,
since every problem argument is a by_value i32 and only names catch a
reordering. The adapter exposes launch_signature()/launch_values() over
ConvArgs, which the benchmark tool now uses.

Mirror rocKE's new direct-conv rule (odd filter, "same" padding) in the
native guard, and refuse an implicit-GEMM reduction extent at or above 2^23
as ConvArgs does.
… run

With the rocKE AOT change the problem shape is passed to the kernel at
runtime, so a packaged kernel is no longer limited to the shape it was
built for. Instead of requiring an exact shape match, the matcher now
checks only what the binary still keeps from its build problem:

- implicit GEMM: grouped vs ungrouped path, the 1x1 fast path, and the
  load/store vector widths, which must divide the graph's channels per
  group
- direct depthwise: filter, stride, padding, and for the spatial
  variant the group count

Grouped 1x1 graphs are now served by grouped kernels. Without
benchmarking, the kernel built for the exact shape is still preferred.

Tests now cover shapes no kernel was built for, running every kernel
that claims them against the CPU reference. The benchmark tool and
docs are updated to match.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants