# Partial Sums: Divide the Work

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

The fix: give *every* thread a slice. 64 threads, each summing 64 of the
4,096 values, produce 64 **partial sums** — and 64 leftover numbers are
cheap to finish off in plain JavaScript.

Watch the reading pattern, though. Thread `x` does *not* take a
contiguous block; it reads `data[x]`, `data[x + 64]`,
`data[x + 128]`, … — a **strided** walk. At every step of the
loop, neighbouring threads touch neighbouring elements, which is exactly the access
pattern GPU memory hardware is built to serve in one go.

## Figures

- **thread x takes every 64th element — neighbours read neighbours at every step**

## Goal

**Goal:** compute 64 strided partial sums on the GPU, then total the
64 partials in JavaScript and log the grand total.

## Requirements

- Each of the 64 threads loops `this.constants.chunk` times
- Strided reads: element `i` of thread `x` is `data[i * this.constants.threads + this.thread.x]`
- Sum the 64 returned partials in plain JavaScript and `console.log` the total

## Hint 1 — which elements are mine?

Thread `x` owns elements `x`, `x + 64`,
`x + 128`, … so its `i`-th element sits at index
`i * 64 + x`.

## Hint 2 — the loop body

```js
sum += data[i * this.constants.threads + this.thread.x];
```

## Hint 3 — finishing in JS

After `const partial = await partials(data);` a plain loop does it:

```js
let total = 0;
for (let i = 0; i < partial.length; i++) {
  total += partial[i];
}
```

## Same idea elsewhere

This is CUDA's *grid-stride loop*, almost line for line — every serious
reduction in CUB and Thrust starts with per-thread partials accumulated in registers,
and coalesced (strided-by-thread-count) reads are the whole reason for the pattern.
WebGPU and Metal compute kernels stage the same partials into workgroup/threadgroup
memory.

## Starter code

```js
// 64 threads, 64 values each. Strided reads keep the memory hardware happy.
const gpu = new GPU({ mode });

const partials = gpu.createKernel(function (data) {
  // TODO: loop this.constants.chunk times and accumulate this thread's
  // strided slice: data[i * this.constants.threads + this.thread.x]
  return 0;
}, {
  output: [64],
  constants: { threads: 64, chunk: 64 },
});

const partial = await partials(data);
console.log('partials:', partial.length);

let total = 0;
for (let i = 0; i < partial.length; i++) total += partial[i];
console.log('total:', total);
```

---

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

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