bhanc commited on
Commit
f3a5634
·
verified ·
1 Parent(s): 4773683

Remove backend experiment notes from the published model repository

Browse files
Files changed (3) hide show
  1. README.md +2 -6
  2. vulkan/NOTES.md +0 -90
  3. xnnpack/NOTES.md +0 -119
README.md CHANGED
@@ -48,15 +48,13 @@ These measure export agreement, not accuracy against ground-truth masks.
48
  Choose FP32 when boundary precision matters.
49
 
50
  Full-network INT8 remains unpublished because it loses substantial foreground
51
- detail. See [XNNPACK precision notes](xnnpack/NOTES.md) for the selective recipe,
52
- calibration, validation and rejected alternatives.
53
 
54
  Vulkan FP16 preserves input normalization and one sensitive convolution in FP32.
55
  On a Galaxy S20+ (Android 13, Mali), native forward medians were 337 ms for this
56
  variant, versus 316 ms for XNNPACK FP32 and 189 ms for selective INT8. Android uses the standard Vulkan-first default when the Vulkan backend is
57
  linked. Performance varies by device. Across 13 device-tested images, Vulkan FP16 averaged 0.9945 mask IoU
58
- against FP32 (minimum 0.9854). See [Vulkan precision notes](vulkan/NOTES.md)
59
- for the export recipe, phone validation and timing limitations.
60
 
61
  ## Repository structure
62
 
@@ -66,10 +64,8 @@ coreml/config.json 1.5 kB
66
  coreml/u2netp_coreml_fp16.pte 3.3 MB
67
  coreml/u2netp_coreml_fp32.pte 5.5 MB
68
  vulkan/config.json 886 B
69
- vulkan/NOTES.md 4.1 kB
70
  vulkan/u2netp_vulkan_fp16.pte 2.4 MB
71
  xnnpack/config.json 1.5 kB
72
- xnnpack/NOTES.md 6.6 kB
73
  xnnpack/u2netp_xnnpack_fp32.pte 4.6 MB
74
  xnnpack/u2netp_xnnpack_int8.pte 4.0 MB
75
  LICENSE 11.4 kB
 
48
  Choose FP32 when boundary precision matters.
49
 
50
  Full-network INT8 remains unpublished because it loses substantial foreground
51
+ detail.
 
52
 
53
  Vulkan FP16 preserves input normalization and one sensitive convolution in FP32.
54
  On a Galaxy S20+ (Android 13, Mali), native forward medians were 337 ms for this
55
  variant, versus 316 ms for XNNPACK FP32 and 189 ms for selective INT8. Android uses the standard Vulkan-first default when the Vulkan backend is
56
  linked. Performance varies by device. Across 13 device-tested images, Vulkan FP16 averaged 0.9945 mask IoU
57
+ against FP32 (minimum 0.9854).
 
58
 
59
  ## Repository structure
60
 
 
64
  coreml/u2netp_coreml_fp16.pte 3.3 MB
65
  coreml/u2netp_coreml_fp32.pte 5.5 MB
66
  vulkan/config.json 886 B
 
67
  vulkan/u2netp_vulkan_fp16.pte 2.4 MB
68
  xnnpack/config.json 1.5 kB
 
69
  xnnpack/u2netp_xnnpack_fp32.pte 4.6 MB
70
  xnnpack/u2netp_xnnpack_int8.pte 4.0 MB
71
  LICENSE 11.4 kB
vulkan/NOTES.md DELETED
@@ -1,90 +0,0 @@
1
- # Vulkan precision and Android validation
2
-
3
- The published FP16 variant accepts RGB float32 `[1,3,320,320]` in `[0,1]` and returns float32
4
- `[1,1,320,320]` foreground logits. Input normalization stays in FP32. The
5
- export contains one Vulkan delegate for the network and one portable input
6
- `amax` reduction. Texture limits are capped at 2048 in each dimension.
7
-
8
- ## FP16 with a sensitive FP32 convolution
9
-
10
- The FP16 export fuses Conv/BatchNorm pairs before casting the network to half.
11
- `stage2d.rebnconv1d.conv_s1` retains FP32 weights, bias and computation, with
12
- casts around it inside the Vulkan delegate. Global `force_fp16` is deliberately
13
- not used: it would also downcast this convolution and input normalization.
14
-
15
- On the connected Galaxy S20+, an entirely FP16 export changed the bicycle mask
16
- to 0.9418 IoU against XNNPACK FP32. Keeping this convolution in FP32 recovered
17
- 0.9932 IoU. The entirely FP16 candidate is not published.
18
-
19
- ## Device checks
20
-
21
- Validation used Samsung Galaxy S20+ SM-G986B, Android 13, Mali GPU, arm64-v8a,
22
- and the ExecuTorch 1.4.1 runtime/backend libraries shipped with RNE. A native
23
- runner linked these exact libraries, loaded each actual `.pte`, checked float32
24
- output type and element count, rejected non-finite output, and saved logits.
25
- Exported method metadata was also checked against the config.
26
-
27
- The comparison set is the same 13 images used for selective XNNPACK INT8
28
- validation: `bike.jpg`, `boat.jpg`, `whisk.png`, plus COCO val2017 image IDs 139,
29
- 285, 632, 724, 776, 785, 802, 872, 885 and 1000. All-black and all-white inputs
30
- were also checked. These are agreement measurements against the shipped
31
- XNNPACK FP32 `.pte`, not ground-truth segmentation accuracy.
32
-
33
- | Variant | Mean mask IoU (13 images) | Minimum mask IoU | File size |
34
- | --- | --- | --- | --- |
35
- | Vulkan FP16 with one FP32 convolution | 0.9945 | 0.9854 | 2,437,516 B |
36
-
37
- The FP16 probability MAE was at most 0.00444 across those 13 images. The published
38
- variant produced finite outputs on all 15 inputs.
39
-
40
- Warm native forward measurements on the same bicycle input used three warm-up
41
- runs followed by ten measured runs per variant:
42
-
43
- | Variant | Median |
44
- | --- | --- |
45
- | XNNPACK FP32 | 315.6 ms |
46
- | XNNPACK selective INT8 | 189.1 ms |
47
- | Vulkan FP16 with one FP32 convolution | 337.2 ms |
48
- | Vulkan FP32 (unpublished trial) | 403.1 ms |
49
-
50
- These were sequential host-driven device checks, not interleaved benchmarks;
51
- they exclude model loading, image preprocessing and rendering. Vulkan does not
52
- win on this older Mali GPU. Android uses the standard Vulkan-first default
53
- when the Vulkan backend is linked. Select XNNPACK INT8 for the faster option
54
- on this tested phone; performance varies by device. A trial with only four half-precision convolutions was
55
- also slower (421.9 ms) and is not published.
56
-
57
- ## Reproducing the export environment
58
-
59
- The Vulkan AOT implementation is pinned to software-mansion-labs/executorch
60
- `@ms/separate-backends-1.4.1`, commit
61
- `0de5ce9470e4a18d6d45585f69519267bbe218b9`. Torch is 2.14.0. The nested
62
- `pyproject.toml` records the fork dependency; see the repository Vulkan skill
63
- for the source-built environment used by other Vulkan models.
64
-
65
- For AOT-only export, a compatible ExecuTorch 1.4.1 wheel can provide the common
66
- serialization binaries while the fork supplies its Vulkan Python package.
67
- No host GPU runtime is needed; Android validation still uses the shipped native
68
- Vulkan library. Clone the fork into a directory named `executorch`, check out
69
- the commit above, then from export-scripts run:
70
-
71
- ```bash
72
- uv run --project exporter_models/u2netp python - /path/to/executorch <<'PY'
73
- import runpy
74
- import sys
75
- from pathlib import Path
76
- import executorch.backends
77
-
78
- fork = Path(sys.argv[1]).resolve()
79
- executorch.backends.__path__.insert(0, str(fork / "backends"))
80
- sys.argv = [
81
- "exporter", "export", "u2netp", "--backend", "vulkan", "--all-variants",
82
- "--output-dir", "exports/u2netp/vulkan",
83
- ]
84
- runpy.run_module("exporter.cli", run_name="__main__")
85
- PY
86
- ```
87
-
88
- The release FP16 export was byte-identical to the device-validated candidate.
89
- The Python wheel's native runtime cannot execute Vulkan on this Mac; it was
90
- not used as a substitute for phone validation.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
xnnpack/NOTES.md DELETED
@@ -1,119 +0,0 @@
1
- # XNNPACK precision experiments
2
-
3
- FP32 and selective INT8 are published. Full-network static INT8, an earlier
4
- mixed INT8/FP32 recipe and FP16 were rejected because they changed the masks.
5
-
6
- ## Selective INT8 (published)
7
-
8
- The final recipe quantizes only `stage1d.rebnconvin`, `stage1d.rebnconv1d`,
9
- `stage2d.rebnconvin` and `stage2.rebnconvin`. These convolutions dominate host
10
- latency. Remaining convolutions, concatenations and residual additions stay
11
- FP32. Public I/O and normalization are unchanged.
12
-
13
- PT2E uses per-channel symmetric INT8 weights and per-tensor affine INT8
14
- activations with HistogramObserver. The weight observer minimum scale is
15
- float32 epsilon. Calibration uses the same 13 pinned upstream images listed
16
- below. Export scripts download these images automatically.
17
-
18
- ExecuTorch 1.4.1's concatenation annotator ignores its filter argument, so
19
- module exclusions alone do not keep skip connections in FP32. The export
20
- selects only convolution operators, with an explicit module filter. Weight
21
- attributes are allowed through this filter because they lack module-stack
22
- metadata. This avoids quantizing unrelated concatenations.
23
-
24
- Actual `.pte` execution was checked against the published FP32 `.pte` on the
25
- three upstream images below plus ten COCO val2017 images, IDs 139, 285, 632,
26
- 724, 776, 785, 802, 872, 885 and 1000. None was used for calibration. Average
27
- mask IoU was 0.9953, minimum 0.9868; probability MAE ranged from 0.00015 to
28
- 0.00543. All-black and all-white inputs also produced finite outputs.
29
-
30
- | Image | Selective INT8 mask IoU | Probability MAE |
31
- | ----------- | ---------------------- | --------------- |
32
- | `bike.jpg` | 0.9947 | 0.00158 |
33
- | `boat.jpg` | 0.9956 | 0.00152 |
34
- | `whisk.png` | 0.9992 | 0.00055 |
35
-
36
- On an Apple M1 Pro, 30 interleaved ExecuTorch runs after five warm-ups measured
37
- 156.0 ms median for FP32 and 87.4 ms for selective INT8 (1.78× faster). File
38
- sizes were 4,610,948 and 4,007,684 bytes. These are host measurements, exclude
39
- RNE preprocessing/rendering, and need on-device confirmation. This small
40
- sample measures conversion agreement, not ground-truth segmentation accuracy.
41
-
42
- The event-traced ExecuTorch 1.4.1 runtime and cloned profiler confirmed all
43
- four selected convolutions execute as quantized XNNPACK kernels. Over five
44
- real-input executions, the delegate accounted for 99.36% of method time and
45
- the portable input `amax` for 0.63%.
46
-
47
- ## Static INT8
48
-
49
- The experiment used PT2E `prepare_pt2e` / `convert_pt2e`,
50
- `XNNPACKQuantizer`, and `get_symmetric_quantization_config(is_per_channel=True)`:
51
- static INT8 activations with per-channel INT8 weights. Public inputs and
52
- outputs remained float32. The export included the same image-maximum and
53
- ImageNet normalization as FP32, and returned foreground logits before sigmoid.
54
-
55
- Calibration used 13 RGB images from the upstream repository at commit
56
- `ac7e1c817ecab7c7dff5ce6b1abba61cd213ff29`, resized to 320×320:
57
- `0002-01.jpg`, `0003.jpg`, `girl.png`, `hockey.png`, `horse.jpg`, `im_01.png`,
58
- `im_14.png`, `im_21.png`, `im_27.png`, `lamp2_meitu_1.jpg`, `long.jpg`,
59
- `rifle1.jpg`, and `sailboat3.jpg`.
60
-
61
- The three images below were held out from calibration. Results compare actual
62
- ExecuTorch `.pte` execution against the shipped FP32 `.pte`. Mask IoU uses a
63
- foreground-probability threshold of 0.5; MAE is measured after sigmoid in [0,1].
64
- These measure conversion agreement, not accuracy against ground-truth masks.
65
-
66
- | Image | Static INT8 mask IoU | Static INT8 probability MAE | Mixed INT8 mask IoU | Mixed INT8 probability MAE |
67
- | ----------- | -------------------- | --------------------------- | ------------------- | -------------------------- |
68
- | `bike.jpg` | 0.6692 | 0.09813 | 0.9629 | 0.01421 |
69
- | `boat.jpg` | 0.8703 | 0.04655 | 0.9410 | 0.02156 |
70
- | `whisk.png` | 0.9387 | 0.06170 | 0.9945 | 0.00458 |
71
-
72
- Static INT8 is smaller and faster, but loses substantial foreground detail.
73
- Those mask changes outweigh the size and latency improvements.
74
-
75
- ## Mixed INT8/FP32
76
-
77
- The earlier candidate excluded convolutions in `stage1`, `stage2`, `stage1d`,
78
- `stage2d`, `side1`, `side2`, and `outconv`, using the same calibration data.
79
- The concatenation-filter issue described above still quantized skip connections,
80
- including those inside excluded modules. Agreement improved, but the boat mask
81
- still fell to 0.9410 IoU and the latency gain was small. This candidate is not
82
- published. The selective recipe above replaces this approach.
83
-
84
- ## Host size and latency
85
-
86
- Interleaved measurements used the same bicycle input, three warm-up calls,
87
- then 20 executions per candidate through ExecuTorch on an Apple M1 Pro running
88
- macOS 26.5.2, with torch 2.14.0, ExecuTorch 1.4.1 and torchao 0.18.0.
89
-
90
- | Candidate | File size | Median inference |
91
- | -------------------------- | --------- | ---------------- |
92
- | FP32 (published) | 4.61 MB | 217 ms |
93
- | Static INT8 (rejected) | 1.36 MB | 64 ms |
94
- | Mixed INT8/FP32 (rejected) | 2.61 MB | 215 ms |
95
-
96
- Other export/build work was running on the host, so these are indicative
97
- comparisons rather than isolated device benchmarks. They exclude RNE image
98
- preprocessing and rendering. The small calibration/validation sample does not
99
- prove that every quantization strategy is unsuitable; it establishes why these
100
- particular candidates were not shipped. A future attempt needs more calibration
101
- coverage and a larger independent quality evaluation before publication.
102
-
103
- ## FP16 trial
104
-
105
- An XNNPACK FP16 candidate kept input normalization and public I/O in FP32 and
106
- fused each Conv/BatchNorm pair before converting the network to FP16. Eager
107
- agreement looked promising, but the actual exported runtime shifted the bicycle
108
- mask to 0.9549 IoU (probability MAE 0.01111) against the shipped FP32 model.
109
- It is not published either. This result is specific to the XNNPACK FP16
110
- candidate; the published CoreML FP16 artifact was validated separately.
111
-
112
- ## Delegation
113
-
114
- A local event-traced ExecuTorch 1.4.1 build and `executorch-profiler` measured
115
- five FP32 executions: 99.68% of elapsed time was inside the XNNPACK delegate and
116
- 0.31% was the portable `amax` input reduction. Convolution dominated execution.
117
- These are timing shares, not a count of delegated graph operators. Removing
118
- the reduction would not address the main cost and would change the upstream
119
- image-dependent input normalization.