Skip to content
Sample of Parallel Reduction (WebGPU workgroup-shared-memory tree reduction)

anadol_webgpu · parallelReduction

Parallel Reduction (WebGPU workgroup-shared-memory tree reduction)

The classic WebGPU parallel-reduction pattern: load N values into workgroup-shared memory, workgroupBarrier(), tree-reduce by stride (shared[lid.x] = op(shared[lid.x], shared[lid.x + stride]); stride /= 2), workgroupBarrier(), and emit per-workgroup partials from thread 0. A second dispatch (or atomics) reduces those to a single scalar. Here the algorithm is re-implemented in numpy level-by-level, and each intermediate level of the reduction tree is rendered as a horizontal bar chart (leaves at top, root scalar at bottom) so the spatial structure of the reduction is directly observable. Stepping refills the input array with a different seed, animating the reduction in time.

Original: https://www.mysimulator.uk/content/articles/webgpu-compute.html

▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.

Family
anadol_webgpu
Source
anadol · webgpu
Evolution
compute
Render
bar_chart_levels
Complexity
medium
Agents
65536
Year
2024
Author
WebGPU compute primitives (concept)

Math essence

Initialise a length-N array of doubles (sin+cos+noise+spikes). Apply a binary tree reduction op ∈ {sum, max, mean}; intermediate levels L[0..k] saved. Render row r with horizontal bars whose heights equal the L[r] elements (normalised per-level). Repeating with a fresh seed each step animates the level rows.

Parameters

Name Type Default Range Description
dim int 600 200–1500 Square canvas side length.
array_size int 65536 256–1048576 Array length N (power of 2 preferred).
workgroup_size int 256 32–1024 Equivalent WebGPU @workgroup_size.
mode str sum null–null sum|max|mean — reduction operator.
data_seed int 42 0–2147483647 Input array seed (incremented each step).
data_scale float 1 0–10 Input scaling.
bar_height_max float 220 20–600 Max bar height in px.

Reference

First 60 lines of reference.py. Full source: library_external/anadol_webgpu/parallelReduction/reference.py

"""parallelReduction — WebGPU parallel reduction primitive.

The WebGPU 'parallel reduction' pattern reduces an array of N elements
to a single scalar (or per-workgroup vector) using a tree-of-sums in
workgroup-shared memory.  This is the same primitive used in
histograms, image moments, mean/max/sum statistics, and the first
phase of a softmax / dot-product kernel.

Reference implementation in WGSL (illustrative):

    const WS = 256u;
    var<workgroup> sh : array<f32, WS>;
    @compute @workgroup_size(WS)
    fn reduce_sum(
        @builtin(global_invocation_id) gid : vec3u,
        @builtin(local_invocation_id)  lid : vec3u,
        @builtin(workgroup_id)         wid : vec3u,
    ) {
        let i = gid.x;
        let n = arrayLength(&data);
        sh[lid.x] = select(0.0, data[i], i < n);
        workgroupBarrier();
        var stride = WS / 2u;
        loop {
            if (stride == 0u) { break; }
            if (lid.x < stride) {
                sh[lid.x] = sh[lid.x] + sh[lid.x + stride];
            }
            workgroupBarrier();
            stride /= 2u;
        }
        if (lid.x == 0u) { result[wid.x] = sh[0]; }
    }

A second dispatch then sums the per-workgroup partials.

Here we reduce a synthesised array of N floats and render the
workgroup-block partials as a 1D bar chart so the spatial structure
of the reduction (root-of-tree semantics) is directly visible.

Reference:
- https://www.mysimulator.uk/content/articles/webgpu-compute.html
  (parallel reduction using shared memory in WGSL)
- https://webgpufundamentals.org/webgpu/lessons/webgpu-compute-shaders.html
"""
from __future__ import annotations

from typing import ClassVar

import numpy as np


class ParallelReduction:
    """Workgroup-tree parallel reduction visualised as a 1D bar chart.

    Parameters
    ----------
    dim : int
        Square canvas side length (px).
    array_size : int

Try running it locally

The reference implementation is self-contained Python with numpy. Install the package and run:

python library_external/anadol_webgpu/parallelReduction/reference.py

Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.

More from anadol · webgpu

Sample of 2D FFT Texture Spectrum (WebGPU butterfly FFT)

2D FFT Texture Spectrum (WebGPU butterfly FFT)

anadol_webgpu · fft2dTexture

The WebGPU butterfly 2D FFT pattern: stage by stage, a @compute shader reads two texels per output (input[p] and twiddle-weighted input[q]) and writes the combined result; after log2(N) horizontal stages, transpose, and log2(N) vertical stages, the 2D FFT is complete.

View →
Sample of Compute Particle System (WebGPU @compute pattern)

Compute Particle System (WebGPU @compute pattern)

anadol_webgpu · computeParticleSystem

The canonical WebGPU 'compute-to-render' pattern: a @compute shader updates N particles in a storage buffer (one thread per particle, simple Verlet-style integration: v += gravity; v *= drag; p += v; bounce off walls; life++; respawn if life>max), and a render pass consumes the same buffer as vertex data to draw point sprites.

View →
Sample of Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)

Data Particle Field (Refik Anadol — Machine Hallucinations / AI Data Sculptures)

anadol_webgpu · dataParticleField

Inspired by Refik Anadol Studio's AI Data Sculptures and 'data universe' portraits (e.g.

View →
Sample of Dreamscape Field (Refik Anadol — Dreams / Nature Dreams)

Dreamscape Field (Refik Anadol — Dreams / Nature Dreams)

anadol_webgpu · dreamscapeField

Inspired by Refik Anadol Studio's Dreams series (Nature Dreams, Urban Dreams, Space Dreams and the MoMA Fluid Dreams algorithm): a smooth low-frequency Perlin noise field drives slow global drift while a finer detail octave adds turbulent perturbation — Anadol's fluid solver aesthetic realised with cheap numpy.

View →
Sample of Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)

Latent Walk (Refik Anadol — Unsupervised / Machine Hallucinations)

anadol_webgpu · latentWalk

Inspired by Refik Anadol Studio's Unsupervised — Machine Hallucinations — MoMA (2022): a chain of N points is sampled from a synthetic 64-dimensional latent space (a smoothed random walk) and projected to 2D via a fixed random matrix; the path is integrated step-by-step with spherical-linear interpolation between adjacent chain points, so the rendered trail visualises the path the 'latent space browser' would take through the embedding.

View →
Sample of Tile Blur (WebGPU separable Gaussian tile-shared-memory blur)

Tile Blur (WebGPU separable Gaussian tile-shared-memory blur)

anadol_webgpu · tileBlur

The WebGPU separable Gaussian blur primitive: a workgroup of TILE×TILE threads loads a tile+halo of the source image into workgroup-shared memory, workgroupBarrier(), convolves each pixel with a 1D Gaussian along the row, writes to a ping-pong texture; then a second compute pass applies the column-direction Gaussian on the intermediate texture.

View →

See all anadol_webgpu artworks →