--- license: bsd-2-clause base_model: it4lia/irene tags: - executorch - android - weather - nowcasting - precipitation - radar --- # IRENE on-device — ExecuTorch per-step cells (fp16, XNNPACK) Mobile inference graphs for [IRENE](https://huggingface.co/it4lia/irene), the ConvGRU ensemble precipitation-nowcasting model (64M params, © FBK DSIP, BSD-2-Clause). Exported from the released `model.ckpt` as **per-timestep cells**: the caller drives both recurrences in a loop, carrying the five per-block ConvGRU hidden states — so the forecast rollout length and the input-history length are loop counts, not export parameters. One encoder/decoder pair per domain size. Produced by `export_executorch.py --cells --fp16` in the irene-android repo (wrappers and the full I/O contract in its `export/common.py`; parity gate in `export/parity_step.py`). ## Graph contract (num_blocks=5 ⇒ divisor 32) | graph | inputs | outputs | |---|---|---| | `encoder_step` | `frame (1,1,H,W)` normalized reflectivity + states `e1 (1,1,H,W) … e5 (1,256,H/16,W/16)` (zeros at t=0) | `e1'..e5'` + `h1..h5` (downsampled block outputs, deepest first — the **last** step's are the decoder's initial states) | | `decoder_step` | `noise_t (1,1024,H/32,W/32)` ~N(0,1) + states `h1..h5` | `frame_t (1,1,H,W)` normalized, unclamped + `h1'..h5'` | All I/O is **fp16** (no in-graph casts). Pre/post-processing lives in the caller: pad to /32 → NaN→0 → Marshall–Palmer `dBZ = 10·log10(200·R^1.6+1e-16)` clip [0,60] → `/30−1`; inverse + crop on the way out. Per ensemble member: re-seed the decoder states from the encoder skips and draw fresh noise per step. Trained config: 6 input frames, 12 forecast steps (5-min cadence); longer rollouts run mechanically but are beyond the trained horizon. Two integration warnings (cost us a day each): - On Android, `Module.forward` output tensors alias the runtime's memory arena — **copy every carried state** before the next call. - Pin the ExecuTorch runtime to the exporting version: **1.4.0** (delegate blobs do not cross versions). ## Files | file | raw | zst | |---|---|---| | `encoder_step_{256x256,512x512,1024x1024,1408x1216}_fp16.pte` | 15.1 MB each | 7.9 MB each | | `decoder_step_{256x256,512x512,1024x1024,1408x1216}_fp16.pte` | 241.6 MB each | 122.1 MB each | `1408x1216` is the full Italian DPC mosaic (1400×1200, padded to /32); the others are crop sizes in km (1 km cells). Note on size: the weights inside every file are the *same* 64M fp16 parameters; they occupy 2× their fp16 bytes because ExecuTorch ≤1.4 serializes convolution filters as fp32 for XNNPACK (`op_conv2d.py` `force_fp32=True` — the f16 conv API takes fp32 filters and packs at load). That's also why zstd compresses them almost exactly 2:1 (the upcast halves have zero low-mantissa bits), and why the per-size **patches** below are tiny: the weight bytes are identical across sizes, only the graph skeleton differs. ## Getting the files Each `.pte.zst` is standalone: ```bash zstd -d decoder_step_512x512_fp16.pte.zst sha256sum -c SHA256SUMS.pte ``` Minimal-bandwidth set (~130 MB for all four sizes): download the two 256 files + `patches-from-256/`, then reconstruct: ```bash zstd -d --long=28 --patch-from=decoder_step_256x256_fp16.pte \ decoder_step_1024x1024_fp16.pte.zst-patch -o decoder_step_1024x1024_fp16.pte ``` (decoder patches ~218 KB, encoder patches ~2 KB; all reconstructions are byte-identical, verify with `SHA256SUMS.pte`.) `patches-from-512/` is the same idea against the 512 base — kept for irene-android ≤0.5.9, whose in-app updater patches from 512. ## Validation - Eager cells ≡ the monolithic export ≡ `RadarLightningModel.predict()` **bit-exact** (fixed noise, rain-rate space). - ExecuTorch fp32 cells vs eager: ~1e-4 mm/h mean abs. - These fp16 cells produce output **bit-identical** to the monolithic fp16 export; fp16-vs-fp32 error measured on-device at 0.079 mm/h mean against a 7.2 mm/h ensemble spread. - Measured on a Snapdragon 8 Gen 2 (4 threads, mmap): 512² ≈ 206 ms/step, full grid ≈ 1.3 s/step — a 10-member 1-hour ensemble in ~25 s, a full-grid 2-hour member in ~40 s. ## License BSD-2-Clause, © Fondazione Bruno Kessler (DSIP) — same as the IRENE model these are derived from.