gray-scott
A simulation of the Gray-Scott reaction-diffusion equation on a PX x PY grid of PEs, each owning an
NX x NY tile of the global PX*NX x PY*NY grid. The equations are:
with the parameters Du=0.64 Dv=0.35 F=0.0155 k=0.0505 dt=1.0
(configurable in the code). The equations are discretized using the 9-point
Laplacian (-1.00 centre / 0.20 edge / 0.05 corner) and
integrated in time using forward Euler. u and v are clamped to [0,1]
after each step.
Files
| File | Role |
|---|---|
gs.paint | floorplan: the compute grid plus the halo exchange rouring (bench.paint symlinks here) |
halox.paint | halo exchange routing |
gs.w | the per-PE kernel |
xorsp2.w | xorshift128+ RNG |
make-inputbin.py | writes halox_params.bin and rngstate.bin for miset |
check.py | host reference; compares u.bin/v.bin elementwise |
xorsp_ref.py | host-side xorshift128+, copied from bench/app/xorsp |
Parameters
Specified in test cases listed in test.rc:
| Var | Meaning |
|---|---|
NX, NY | cells per PE |
PX, PY | PEs |
SQ | side of the seeded square, must be <= min(NX,NY) |
NITER | timesteps |
Initial condition
Per PE: u=1, v=0, then an SQ x SQ block of u=0.5, v=0.25 centred in
that PE's own tile, then +-0.02 of uniform noise everywhere.
The noise comes from xorshift128+ with a per-PE 128-bit seed that
make-inputbin.py writes to rngstate.bin and the Makefile misets into
the image. check.py reads the same file, so host and device agree by
construction rather than by a reimplemented seeding rule.
The RNG walks the whole padded (NY+2) x (NX+2) array, halo cells
included — one draw per cell, low 16 bits to u, next 16 to v. Noise
in the halo is overwritten by the first exchange; it is there only to keep
the stream a plain linear walk over fpmem.
Boundary conditions
Reflective, in the zero-gradient sense.
Memory
Five (NY+2)*(NX+2) sp arrays (u v un vn rr) overlaid on fpmem, so
5*2*(NX+2)*(NY+2) 16-bit words against the 48 KB per-PE budget — about
NX=NY=48 before it stops fitting.
Running
make TEST=t1 # one row of test.rc
make TEST='*' # all of them
make clean
| tag | geometry | note |
|---|---|---|
t0 | 1x1 PEs | single PE, every side reflective, no fabric traffic |
t1 | 2x2 PEs | smallest case with all four halo directions live |
tx | 1x3 PEs | one column: both x sides reflective on every PE |
ty | 3x1 PEs | one row: both y sides reflective on every PE |
t2 | 3x3 PEs | interior PE with neighbours on all sides |
t3 | 4x3 PEs of 8x6 | non-square tiles and non-square PE grid |
t4 | 4x4 PEs of 16x16 | 64x64 grid, 100 steps |
t5 | 8x8 PEs of 8x8 | 64 PEs |
check.py compares every interior cell against a host run of the same
update in float32 with the same operation order; observed error is
<= 2e-6, i.e. float32 rounding. The tolerance is 1e-4. For
reference, re-running the host side with periodic instead of reflective
padding misses by 6e-3, and with the PE columns permuted by one, by
9e-2 — so the check does discriminate both the boundary rule and data
placement, not just an aggregate.
Run it
The experimental SDK installs this project beside the tutorial, as projects/gray-scott. Run it like a tutorial: tungsten-tutorials -f projects/gray-scott.
Source code
Every file of this example, as the toolset installs them under share/tutorial/projects/gray-scott/. Select a line number to link to that line.