# Whose Value Lands Here?

*Task 4 of 6 · [Radix Sort](https://gpu.rocks/learn/radix-sort-fd3ff796.md) · GPU.js Learn*

Everything so far produced a **plan**: for each element, the slot it
belongs in. Executing the plan is the one move a kernel does not have.
`out[destinations[i]] = keys[i]` is a **scatter** — a thread
writing somewhere other than its own cell — and gpu.js has no such thing (Thinking in
Parallel makes a whole module of why).

So turn the question round, exactly as you would anywhere else on a GPU. Instead of
*"where does my value go?"*, output slot `x` asks
*"which element wants me?"* — sweep the destinations, find the one that equals
`x`, and take that element's key. Every thread reads the whole plan and writes
one cell. It looks wasteful and it is completely parallel, which on a GPU is the trade
you take.

## Goal

**Goal:** apply the permutation with a gather — output slot
`x` holds the key of the element whose destination is `x`.

## Requirements

- No writes anywhere but your own cell — the answer is a `return`
- Sweep all `this.constants.n` destinations looking for `this.thread.x`
- Return that element's *key*, not its index

## Hint 1 — which comparison?

`destinations[i]` is where element `i` is *going*.
Your cell is `this.thread.x`. So the element you want is the one where
those two are equal — never `keys[destinations[this.thread.x]]`, which
applies the permutation backwards.

## Hint 2 — the sweep

```js
let value = 0;
for (let i = 0; i < this.constants.n; i++) {
  if (destinations[i] === this.thread.x) {
    value = keys[i];
  }
}
return value;
```

## Same idea elsewhere

Compute APIs do let you scatter — CUDA and WebGPU threads can store to any buffer
address — and a production radix sort uses that: it writes keys straight to their computed
offsets, which is why it also needs atomics and shared memory to arrange those offsets
safely. Where you have no scatter, the inversion here is the standard replacement, and it
is the same move a fragment shader has made since the beginning: every output pixel pulls
what it needs.

## Starter code

```js
// The plan is done. Now move the data — without a scatter.
const gpu = new GPU({ mode });

const gather = gpu.createKernel(function (keys, destinations) {
  // TODO: find the element whose destination is THIS cell,
  // and return its key.
  return keys[this.thread.x];
}, {
  output: [64],
  constants: { n: 64 },
});

const sorted = await gather(keys, destinations);
console.log('before:', keys.slice(0, 8).join(' '), '…');
console.log('after: ', Array.from(sorted).slice(0, 8).join(' '), '…');
```

---

Interactive version: https://gpu.rocks/learn/radix-sort-fd3ff796/4

[Previous task](https://gpu.rocks/learn/radix-sort-fd3ff796/3.md) · [Next task](https://gpu.rocks/learn/radix-sort-fd3ff796/5.md)
