Task 3 of 5
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.
output: [64, 64], two loops over the whole gridy * 64 + x: an earlier cell wins a tiethis.thread.xCompute 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.
const other = grid[y][x];
if (y * this.constants.size + x < myIndex) {
if (other >= mine) ahead++;
} else if (other > mine) {
ahead++;
}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;
cub::ArgMax returns a KeyValuePair rather than a value.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.