Task 3 of 5
Here's the mental model that makes GPU code fast: computation on the card is
nearly free — it's the transfers that cost. Every kernel that is
not pipeline: true ends with an implicit download, and passing
that array to the next kernel triggers a re-upload. A three-stage chain without
pipelines pays the toll four times for one result.
The starter below is a fully working three-stage audio chain — normalize, gamma, smooth — and every hop goes through JavaScript. Your job isn't to fix the math. It's to fix the traffic: intermediates become pipeline kernels, and only the final stage returns plain numbers. The chain call itself shouldn't change by a single character.
normalize and gamma pipeline kernelssmooth as a plain kernel — the one download you actually wantawait smooth(await gamma(await normalize(signal))) stays as-isThere's no .toArray() in the starter, but the readbacks are
still there: a non-pipeline kernel's awaited return value is the readback.
Count them: normalize downloads, gamma re-uploads and downloads, smooth re-uploads.
Add pipeline: true to the settings of normalize
and gamma. That's the entire refactor — the chain line already does
the right thing once textures flow through it.
cudaMemcpy DtoH/HtoD, not kernels; in WebGPU the same toll is
mapAsync plus staging-buffer copies. "Keep data resident, read back once
at the end" is performance rule number one on every GPU platform.
This page is an interactive exercise — the editor, the GPU runner and your saved progress need JavaScript. The text above is the full brief.