real_esrgan_x4v3 β ExecuTorch
- Source: xinntao/Real-ESRGAN release v0.2.5.0 (realesr-general-x4v3)
- License: BSD-3-Clause
- Input: [[1, 3, 128, 128]] β RGB 0-1, 128x128 tile
- Output: SR image [1,3,512,512] RGB, nominally 0-1 but not clamped by the model β this one overshoots noticeably (measured: 5.5% of pixels outside 0-1, range -0.28 to 1.22 over ten tiles), which is ordinary ringing for a GAN upscaler. Clamp before display.
Variants
All variants take and return fp32 tensors β swap the .pte file, keep your app code.
| build | file | size (MB) | parity vs fp32 eager (worst corr) | Mac median (ms)* |
|---|---|---|---|---|
| fp32 | real_esrgan_x4v3_xnnpack_fp32.pte |
4.9 | 1.000000 | 33.9 |
| Core ML (fp16, iOS) | real_esrgan_x4v3_coreml_all.pte |
2.7 | 0.999999 | 5.1 |
The Core ML build is the same graph lowered to Apple's Neural Engine instead of XNNPACK, which is CPU-only. Measured on an iPhone 17 Pro across seven models, it runs 3.5x to 13.9x faster (median 12x) at roughly half the file size β for example Depth-Anything-V2-Small at 500.8 ms against 42.7 ms, and MODNet at 81.7 ms against 5.9 ms. It computes in fp16 and is iOS-only; the XNNPACK files stay the portable option and are what runs on Android.
*Mac arm64, single process, median of 10 β a reference point for relative cost only, not a device number (torch eager fp32 on the same machine: 42.3 ms).
Builds that did not earn a slot
- fp16 is not shipped: it comes out at 100% of the fp32 file (4.9 MB vs 4.9 MB), so it buys nothing. XNNPACK serializes convolution weights as fp32 no matter what dtype the graph carries, so on a conv-heavy model fp16 saves no disk and only adds cast operations. Reach for int8 here, not fp16.
Verification (executorch 1.4.0, torch 2.13.0)
Parity is measured against the fp32 eager model on real image input; corr is
the correlation over all elements of each output tensor.
| output | shape | max_abs_diff | corr |
|---|---|---|---|
| 0 | [1, 3, 512, 512] | 1.235e-05 | 1.000000 |
XNNPACK delegate coverage (fp32): 61.3% (106/173 ops); ops left on the portable kernels: aten.gt.Scalar x33, aten.where.self x33, aten.upsample_nearest2d.vec x1
Conversion
torch.export -> to_edge_transform_and_lower(partitioner) -> .pte (conversion scripts: executorch-models)
Notes: int8 does not run on executorch 1.4.0, and the reason is a collision between two workarounds rather than anything about this model. PReLU segfaults on the XNNPACK delegate (upstream #17559, fix #21480 not in the stable wheel), so it has to be excluded from partitioning β and a quantized graph with a portable PReLU between delegated convolutions fails shape propagation at execute. Three conv+PReLU layers reproduce it; the same graph in fp32 is corr 1.000000. Reported at https://github.com/pytorch/executorch/pull/21480
- Downloads last month
- -