Skip to content

POCL: fit tuned work-groups to the ndrange - #939

Open
maleadt wants to merge 2 commits into
mainfrom
tb/pocl-fit-workgroups
Open

maleadt wants to merge 2 commits into
mainfrom
tb/pocl-fit-workgroups

Conversation

@maleadt

@maleadt maleadt commented Oct 28, 2026 •

Copy link
Copy Markdown
Member

Split out of #906.

A launch with a partial work-group runs the bounds-checked kernel for all work-groups, and its work-item loop vectorizes poorly (AArch64 has no masked loads and stores; on an EPYC 7502 (Zen 2), they make a work-group 12× slower). Tuned work-groups now shrink, per dimension, to the largest divisor of the ndrange that keeps at least half the size, so that more launches run unchecked. If no divisor fits, they shrink to a quarter: the launch stays checked, but runs faster in smaller work-groups (axpy over 1000003 elements on 4 threads: 71 µs with divisors only, 31 µs with the quarter). Work-groups only shrink, so the padding stays within what KA.select_launch assumes; explicit sizes are kept.

Per-launch time in µs, including synchronization, on PoCL's queue; Ryzen 9 9950X (Zen 5, 16 cores), median of 3 runs of 31 × 20 ms samples; main is c10ff8cf.

4 threads:

Kernel Main PR
axpy 1000 4.12 4.35
axpy 100000 6.42 5.36
axpy 1000003 81.69 30.96
store 4356 3.83 3.29
stencil 96³ 47.31 43.94
stencil 100³ 60.94 57.20
stencil 126³ 120.41 113.30
stencil 127³ 125.24 126.13

16 threads:

Kernel Main PR
axpy 1000 9.72 6.21
axpy 100000 24.77 14.73
axpy 1000003 33.04 30.14
store 4356 4.82 6.56
stencil 96³ 38.51 37.58
stencil 100³ 40.71 38.17
stencil 126³ 63.74 62.85
stencil 127³ 65.97 67.25

Store 4356 at 16 threads is noisy (10th percentiles: 4.59 → 4.18 µs). Stencil 127³ regresses by 1–2%: no divisor fits, so (127, 32, 1) becomes (127, 8, 1) and the launch stays checked. Stencil 126³ gets (126, 21, 1) and runs unchecked.

Earlier main (pre-#931, same queue path), 4 threads, one run per configuration; times in µs:

Kernel M1 main → PR Xeon E3-1245 v6 main → PR
axpy 100000 66.25 → 24.04 23.56 → 17.96
axpy 1000003 — 146.5 → 128.2
stencil 96³ 1080.5 → 468.1 169.0 → 120.5
stencil 100³ 325.9 → 143.5 208.5 → 136.1
stencil 126³ 588.0 → 256.9 794.5 → 801.6
stencil 127³ 1775.6 → 1776.2 864.0 → 812.2

The stencil is a 7-point Laplacian with an interior if; axpy is y[i] = muladd(a, x[i], y[i]).

@github-actions

github-actions Bot commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Benchmark results

Compared with c42b1f458, the merge base.
Times are the minimum time of every benchmark. A change is unusual when it exceeds both three times the benchmark's typical change between consecutive runs on the default branch and a minimum per category (performance 3%, latency 5%, applications 3%, other 3%). A benchmark that starts or stops allocating is listed however few the allocations. A single run can still be a fluke, so rerun before drawing conclusions.

Geometric mean Unusual: slower Unusual: faster Compared
Performance −0.0% 0 0 32
Latency +0.8% 0 0 13
Applications +19.8% 0 0 5

No unusual changes.

All benchmarks
Benchmark Baseline This PR Change
Performance
julia/serial/arithmetic/muladd-reference 655 µs 655 µs +0.0% noise unknown
julia/serial/math/exp-f64-reference 292 µs 284 µs −2.8% noise unknown
julia/serial/narrow/masked-reference 714 µs 730 µs +2.2% noise unknown
pocl/parallel/atomics/histogram 5.14 ms 5.15 ms +0.2% noise unknown
pocl/parallel/groupreduce/add-f64 1.65 ms 1.65 ms +0.1% noise unknown
pocl/parallel/groupreduce/fallback 19.0 ms 18.1 ms −4.7% noise unknown
pocl/parallel/groupscan/add-i32 2.52 ms 2.52 ms +0.1% noise unknown
pocl/parallel/indexing/cartesian3d 78.5 µs 80.4 µs +2.4% noise unknown
pocl/parallel/indexing/linear3d 80.3 µs 78.1 µs −2.8% noise unknown
pocl/parallel/indexing/ntuple3d 78.7 µs 78.6 µs −0.1% noise unknown
pocl/parallel/indexing/ntuple4d 157 µs 170 µs +8.0% noise unknown
pocl/parallel/localmem/transpose-naive 456 µs 460 µs +0.9% noise unknown
pocl/parallel/localmem/transpose-tiled 92.9 µs 109 µs +17.5% noise unknown
pocl/parallel/private/across-barrier 165 µs 154 µs −6.5% noise unknown
pocl/parallel/scheduling/default 182 µs 181 µs −0.2% noise unknown
pocl/parallel/scheduling/explicit 182 µs 181 µs −0.1% noise unknown
pocl/parallel/stream/copy/cache 781 ns 646 ns −17.3% noise unknown
pocl/parallel/stream/copy/dram 6.41 ms 6.25 ms −2.5% noise unknown
pocl/parallel/stream/triad/cache 7.17 µs 7.69 µs +7.2% noise unknown
pocl/parallel/stream/triad/dram 9.42 ms 9.37 ms −0.5% noise unknown
pocl/parallel/util/copyto-small 24.0 ns 24.0 ns +0.0% noise unknown
pocl/parallel/util/zeros-large 1.01 ms 995 µs −1.1% noise unknown
pocl/parallel/util/zeros-small 619 ns 627 ns +1.3% noise unknown
pocl/serial/arithmetic/contract 1.91 ms 1.90 ms −0.6% noise unknown
pocl/serial/arithmetic/muladd 756 µs 757 µs +0.2% noise unknown
pocl/serial/const/marked 728 µs 699 µs −4.0% noise unknown
pocl/serial/const/unmarked 910 µs 909 µs −0.1% noise unknown
pocl/serial/math/exp-f64 154 µs 147 µs −4.6% noise unknown
pocl/serial/math/sin-f64 194 µs 200 µs +2.8% noise unknown
pocl/serial/narrow/masked 807 µs 832 µs +3.1% noise unknown
pocl/serial/narrow/unmasked 766 µs 810 µs +5.7% noise unknown
pocl/serial/stream/triad/dram 8.62 ms 8.69 ms +0.8% noise unknown
Latency
host/import/ka 501 ms 506 ms +1.0% noise unknown
host/precompile/ka 44.4 s 44.5 s +0.2% noise unknown
host/startup 128 ms 128 ms +0.0% noise unknown
pocl/parallel/launch/dynamic-default 4.37 µs 4.47 µs +2.4% noise unknown
pocl/parallel/launch/groupreduce-f64 6.59 µs 6.69 µs +1.6% noise unknown
pocl/parallel/launch/many-args 11.2 µs 12.1 µs +8.6% noise unknown
pocl/parallel/launch/partial-workgroup 4.25 µs 4.23 µs −0.5% noise unknown
pocl/serial/compile/groupreduce 1.39 s 1.40 s +0.7% noise unknown
pocl/serial/compile/localmem-barrier 697 ms 703 ms +0.9% noise unknown
pocl/serial/compile/new-kernel 117 ms 117 ms −0.4% noise unknown
pocl/serial/compile/new-workgroupsize 14.1 ms 13.5 ms −4.2% noise unknown
pocl/serial/first-kernel/cold-cache 1.95 s 1.94 s −0.0% noise unknown
pocl/serial/first-kernel/warm-cache 279 ms 279 ms −0.1% noise unknown
Applications
pocl/parallel/dgsem/fluxdiff-node 291 µs 450 µs +54.7% noise unknown
pocl/parallel/dgsem/weak-element 159 µs 209 µs +31.4% noise unknown
pocl/parallel/dgsem/weak-node-localmem 119 µs 129 µs +8.5% noise unknown
pocl/parallel/stencil/timestep 7.75 ms 8.51 ms +9.8% noise unknown
pocl/serial/stencil/timestep 11.3 ms 11.5 ms +1.8% noise unknown

History: https://juliagpu.org/perf/?pkg=kernelabstractions

@codecov

codecov Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 84.11%. Comparing base (c42b1f4) to head (9093deb).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #939      +/-   ##
==========================================
- Coverage   84.80%   84.11%   -0.70%     
==========================================
  Files          31       31              
  Lines        2593     2562      -31     
==========================================
- Hits         2199     2155      -44     
- Misses        394      407      +13     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

A launch with a partial work-group runs the bounds-checked kernel, whose
work-item loop vectorizes poorly. Shrink each dimension of the tuned size
to the largest divisor of the ndrange that keeps at least half of it. On
an M1, a 126³ stencil takes 257 µs instead of 588.
Such launches run the bounds-checked kernel anyway, and run it faster in
smaller work-groups: axpy over 1000003 elements on 4 threads takes 31 µs
instead of 71 on a Ryzen 9 9950X, and 128 instead of 146 on an EPYC 7502.
@maleadt
maleadt force-pushed the tb/pocl-fit-workgroups branch from 415cc6b to 9093deb Compare November 4, 2026 09:12

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant