Task 4 of 4

When the CPU Wins

Sixteen numbers, doubled. The GPU can do it — but every kernel call pays a fixed toll before any math happens: dispatch through the graphics API, upload 16 values, read 16 back. A plain JavaScript loop finishes the whole job in nanoseconds, before the GPU has cleared its throat.

This is the module's payoff — the full honest-measurement checklist in one run: warm up first (task 1), remember the transfer toll (task 2), compare results with a tolerance (task 3), and then declare the true winner — even when it isn't the GPU. Parallel hardware pays off on big workloads; on tiny ones, the honest answer is a for-loop.

Goal: double tiny both ways — kernel and plain loop — verify they agree within a tolerance, time both fairly, and log the winner.

Requirements

Hint 1 — the tolerant match

Task 3's move, in a loop: start with let allMatch = true; and flip it to false whenever Math.abs(fromKernel[i] - fromLoop[i]) > 1e-4.

Hint 2 — a fair fight

The first doubleTiny(tiny) call already warmed the kernel up, so both timed loops measure steady state. Time 200 rounds of doubleTiny(tiny), then 200 rounds of the JS loop, and divide each total by 200.

Hint 3 — declaring the winner
console.log('winner:', kernelMs < loopMs ? 'gpu kernel' : 'plain js');

On a job this small, expect the loop to take it. That's the honest answer.

Same idea elsewhere

Kernel-launch overhead runs to microseconds on CUDA and ROCm — thousands of CPU instructions' worth per launch. It's why serious frameworks batch and fuse tiny operations instead of dispatching them one at a time, and why "is this workload big enough?" is the first question asked in any GPU port.

All tasks in Measuring Speed Honestly

  1. The First Call Is a Lie
  2. Pay the Transfer Tax
  3. Two Machines, Two Answers
  4. When the CPU 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.