Task 4 of 6

Ride the Ladder Down

Now ride it all the way: 1,024 → 512 → 256 → … → 1. Ten rungs and the array is a scalar. That means the same kernel has to run at a different size on every call — two options make that legal: dynamicOutput: true lets setOutput() shrink the thread grid between calls, and dynamicArguments: true lets the input shrink with it.

The driving loop lives in JavaScript, but every rung of actual work stays parallel on the GPU: log₂(1024) = 10 launches instead of 1,023 serial additions. One real-world wrinkle, already wired into the driver: gpu.js locks an argument's type on the kernel's first call, so the ladder starts from a Float32Array — the same type every rung's output comes back as.

halve, halve, halve — the ladder every platform climbs
Goal: reduce the 1,024 values of data to a single total by iterating the halving rung, and log the result.

Requirements

Hint 1 — resizing a kernel

halve.setOutput([n]) takes the new output shape as an array. Call it before each invocation, with n already halved.

Hint 2 — the driver skeleton
let n = values.length;
while (n > 1) {
  n = n / 2;
  // …
}

— inside the loop, resize, re-invoke, and keep the returned array for the next rung.

Hint 3 — the full driver
while (n > 1) {
  n = n / 2;
  halve.setOutput([n]);
  values = await halve(values);
}

— then the answer is values[0].

Same idea elsewhere

Multi-pass reduction is the production pattern everywhere: CUDA launches a shrinking sequence of grids (or grid-syncs with cooperative groups), WebGPU records repeated dispatches ping-ponging between two buffers, Metal encodes one compute pass per rung. The log₂(n) staircase is identical on all of them.

All tasks in Reductions

  1. The One-Thread Trap
  2. Partial Sums: Divide the Work
  3. One Rung of the Ladder
  4. Ride the Ladder Down
  5. Min and Max: Change the Operator
  6. Payoff: Mean and RMS, Fused

This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.