# Ride the Ladder Down

*Task 4 of 6 · [Reductions](https://gpu.rocks/learn/reductions-3dadc130.md) · GPU.js Learn*

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.

## Figures

- **halve, halve, halve — the ladder every platform climbs**

## Goal

**Goal:** reduce the 1,024 values of `data` to a single
total by iterating the halving rung, and log the result.

## Requirements

- Create the rung kernel with `dynamicOutput: true` and `dynamicArguments: true`
- Fold pairs with `this.output.x`, exactly like the last task
- Loop in JS: while `n > 1`, halve `n`, `setOutput([n])`, re-invoke
- `console.log` the final scalar

## 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

```js
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

```js
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.

## Starter code

```js
// Same rung as before — but dynamic, so it can shrink call by call.
const gpu = new GPU({ mode });

const halve = gpu.createKernel(function (data) {
  // TODO: fold this thread's pair, exactly like the last task
  return data[this.thread.x];
}, {
  dynamicOutput: true,
  dynamicArguments: true,
});

// Start from a Float32Array: gpu.js locks an argument's type on the first
// call, and every rung's output comes back as a Float32Array.
let values = Float32Array.from(data);
let n = values.length;
while (n > 1) {
  n = n / 2;
  halve.setOutput([n]);
  values = await halve(values);
}
console.log('total:', values[0]);
```

---

Interactive version: https://gpu.rocks/learn/reductions-3dadc130/4

[Previous task](https://gpu.rocks/learn/reductions-3dadc130/3.md) · [Next task](https://gpu.rocks/learn/reductions-3dadc130/5.md)
