flow 1.3.0
Kokkos cut-cell IBM incompressible Navier-Stokes solver + pnm pore extraction
Loading...
Searching...
No Matches
vof_block_packing.py
Go to the documentation of this file.
1#!/usr/bin/env python3
2"""WO-V9 item 4 (second half) — the block gather/scatter packing, device vs host, on a QUIET GPU.
3
4WO-W12 measured 2.731 ms (device) vs 4.626 ms (host) = 1.69x on a comparatively quiet GPU and
579.4 vs 63.4 ms = 0.80x with five other jobs on it, and asked for the number to be re-taken on an
6idle machine. This is that measurement: the 64-marker swarm of the W12 `swarm` gate, kinematic
7block advection (`advect_vof_blocks`), device staging on and off, alternated so a drift in machine
8state shows up as scatter rather than as a result.
9
10 PYTHONPATH=$PWD/build_cuda python tests/study/vof_block_packing.py
11"""
12import argparse
13import time
14
15import numpy as np
16
17import peclet.flow as flow
18
19
20def build(n, seeds, device, pool):
21 s = flow.Solver(n, n, n)
22 s.set_rho(1.0)
23 s.set_mu(0.01)
24 s.set_pressure_geometry(np.full((n, n, n), 10.0, order="F"))
25 s.enable_vof()
26 s.set_vof(np.zeros((n, n, n), order="F"))
27 # a solenoidal cellular field, so the kinematic advection is admissible
28 s.set_dt(0.05)
29 s.enable_vof_blocks(seeds)
30 s.diagnostics.set_vof_block_device_staging(device)
31 s.diagnostics.set_vof_block_pool(pool)
32 return s
33
34
35def seeds_64(n):
36 out, k = [], 0
37 for i in range(4):
38 for j in range(4):
39 for m in range(4):
40 out.append(((i + 0.5) * n / 4, (j + 0.5) * n / 4, (m + 0.5) * n / 4,
41 2.0 + 7.0 * ((k % 8) / 7.0)))
42 k += 1
43 return out
44
45
46def run(n, seeds, device, pool, steps, warm):
47 s = build(n, seeds, device, pool)
48 for _ in range(warm):
49 s.advect_vof_blocks(0.0)
50 t0 = time.time()
51 for _ in range(steps):
52 s.advect_vof_blocks(0.0)
53 dt = (time.time() - t0) / steps
54 st = s.diagnostics.vof_block_stats()
55 vol = sum(b["volume"] for b in st)
56 del s
57 return dt, vol
58
59
60def main():
61 ap = argparse.ArgumentParser()
62 ap.add_argument("--n", type=int, default=48)
63 ap.add_argument("--steps", type=int, default=60)
64 ap.add_argument("--warm", type=int, default=10)
65 ap.add_argument("--reps", type=int, default=3)
66 a = ap.parse_args()
67 seeds = seeds_64(a.n)
68 print(f"64-marker swarm, {a.n}^3, kinematic block advection (dt = 0, so the timing is the "
69 f"GATHER/SCATTER + the sweeps and nothing else)")
70 rows = {True: [], False: []}
71 vols = {}
72 for r in range(a.reps):
73 for dev in (True, False):
74 t, v = run(a.n, seeds, dev, True, a.steps, a.warm)
75 rows[dev].append(t)
76 vols[dev] = v
77 for dev in (True, False):
78 ts = np.array(rows[dev]) * 1e3
79 print(f" {'device' if dev else 'host '} staging: "
80 f"{ts.min():8.3f} ms/step (min of {a.reps}) {ts.mean():8.3f} +- {ts.std():.3f}")
81 d, h = min(rows[True]), min(rows[False])
82 print(f" device/host speedup: {h/d:.3f}x")
83 print(f" total marker volume device {vols[True]:.6f} host {vols[False]:.6f} "
84 f"|d| {abs(vols[True]-vols[False]):.3e}")
85
86
87if __name__ == "__main__":
88 main()
run(n, seeds, device, pool, steps, warm)