Task 1 of 5

The Increment That Vanishes

On a CPU a histogram is three lines. Make an array of zeros, walk the data, add one to the bin each value belongs to. It is the friendliest loop in programming.

const bins = new Array(16).fill(0);
for (let i = 0; i < data.length; i++) bins[data[i]]++;

Now run that loop on 4,096 threads at once. bins[v]++ is not one operation, it is three — read bin v, add one, write bin v back. Two threads whose values land in the same bin both read 7, both compute 8, both write 8. Two increments went in; one came out. Nothing crashed and nothing warned — a count is just quietly too low, and differently too low every time you run it.

This is not a gpu.js quirk. It is precisely why CUDA ships atomicAdd: the read-modify-write has to become indivisible, and making it indivisible means the colliding threads take turns. gpu.js hands you no atomics and no scatter at all — a thread writes one cell, its own — which forces the formulation that actually transfers: invert the loop. Stop asking "which bin does my value go to?" and start asking "which values belong to my bin?". Start with one bin.

nobody can increment your bin but you — so go and count it yourself
Goal: make the single thread count how many of the 4,096 codes equal this.constants.target.

Requirements

Hint 1 — an accumulator, not an array

The count lives in a local let count = 0; that only this thread can see. That is the whole reason there is nothing to race over: private variables cannot collide.

Hint 2 — the loop body
if (codes[i] === this.constants.target) count++;

Same idea elsewhere

Every compute API gives you the scatter this one withholds — and then charges for it. CUDA and HIP have atomicAdd, WGSL has atomicAdd on an atomic<u32> in a storage buffer, Metal has atomic_fetch_add_explicit. They are correct and they are not free: colliding threads serialize, and a histogram with one hot bin can reduce a whole warp to single file. The gather you are about to write is what the fast implementations fall back to when contention gets bad enough — which is why it is worth knowing even where atomics exist.

All tasks in Histograms & Binning

  1. The Increment That Vanishes
  2. One Thread Per Bin
  3. Where Does 7.35 Go?
  4. Partial Histograms, Then Merge
  5. Payoff: An Image's Tone Histogram

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