Task 3 of 5

The Brightest Pixels

The same two moves, one dimension up. brightness is a 64×64 grid — a sensor frame, a heat map, a saliency map — and the question is which eight cells are brightest. Every thread now scans the grid with two loops instead of one, and "earlier in the array" means earlier in row-major order: the flat index of cell [y][x] is y * 64 + x. (Mind the inversion that catches everyone: the launch shape is given width-first, output: [64, 64], but indexing runs row-first, grid[this.thread.y][this.thread.x].)

The other change is what comes back. The eight brightest values are rarely what anyone wants — you want to know where they are. So the picker returns the flat index rather than the value, and JavaScript decodes it: y = Math.floor(idx / 64), x = idx % 64. Carry the index and you can always look the value back up; carry the value and the location is gone for good.

Goal: rank all 4,096 cells, then return the flat indices of the eight brightest, brightest first.

Requirements

Hint 1 — the same rule, flattened

Compute your own flat index once, before the loops:

const myIndex = this.thread.y * this.constants.size + this.thread.x;

Then compare each visited cell's flat index against it — that is exactly the j < this.thread.x test from task 1, in two dimensions.

Hint 2 — the ranking body
const other = grid[y][x];
if (y * this.constants.size + x < myIndex) {
  if (other >= mine) ahead++;
} else if (other > mine) {
  ahead++;
}
Hint 3 — returning a location

Track the coordinates as you scan and combine them at the end, so nothing has to be pulled apart again:

if (ranks[y][x] === this.thread.x) {
  foundY = y;
  foundX = x;
}

then return foundY * this.constants.size + foundX;

Same idea elsewhere

Finding the brightest few cells of a grid is the last step of a stack of real pipelines: keypoint detection (SIFT/ORB pick local maxima of a response map), object detectors ranking anchor boxes before non-max suppression, astronomy source extraction. They all rank on the device and hand back indices, because the payload behind an index is usually far bigger than a float — the same reason CUDA's cub::ArgMax returns a KeyValuePair rather than a value.

All tasks in Top-K Selection

  1. Rank by Counting
  2. Gather the Winners
  3. The Brightest Pixels
  4. Find the Cutoff Instead
  5. Which One Wins?

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