Upload README.md with huggingface_hub
Browse files
README.md
CHANGED
|
@@ -76,15 +76,23 @@ not throw and does not look wrong — it retrieves worse.
|
|
| 76 |
|
| 77 |
## Verification
|
| 78 |
|
| 79 |
-
| build | file | size (MB) | Mac median (ms)* | worst cosine vs eager | retrieval budget spent |
|
| 80 |
-
|---|---|---|---|---|---|
|
| 81 |
-
| XNNPACK fp32 | `embed_qwen3_embedding_0_6b_xnnpack_fp32.pte` | 2383.7 |
|
| 82 |
-
| XNNPACK fp16 | `embed_qwen3_embedding_0_6b_xnnpack_fp16.pte` | 1192.5 |
|
| 83 |
-
| Core ML fp32 | `embed_qwen3_embedding_0_6b_coreml_all.pte` |
|
| 84 |
|
| 85 |
\*Mac arm64, median of 10, one 256-token sequence — a reference point for relative cost,
|
| 86 |
-
not a device number. Eager fp32 on the same input is
|
| 87 |
-
**6.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
Agreement with eager is the first check and it separates nothing here. The one that decides
|
| 90 |
is the last column: rank all eight test sentences against each other, then ask whether this
|
|
@@ -108,7 +116,7 @@ python convert/check_embed.py qwen3_embedding_0_6b fp32 # or fp16, int8, cor
|
|
| 108 |
|
| 109 |
## Not shipped: int8, and this is the first time it was close
|
| 110 |
|
| 111 |
-
**int8 is
|
| 112 |
shelf manages that. Dynamic int8 quantises the linear weights and leaves the token
|
| 113 |
embedding table in fp32, so it only wins when that table is a small share of the file, and
|
| 114 |
here it is: 151669 x 1024 = **621 MB of the 2384 MB model, 26%**. Every other embedding
|
|
@@ -118,11 +126,11 @@ It is still not published, because the size question and the quality question ar
|
|
| 118 |
different questions:
|
| 119 |
|
| 120 |
```
|
| 121 |
-
worst retrieval score shift 0.
|
| 122 |
closest fp32 top-1 decision 0.0234
|
| 123 |
```
|
| 124 |
|
| 125 |
-
The error is **
|
| 126 |
change any result — but eight deliberately dissimilar sentences are the friendliest corpus
|
| 127 |
a retrieval model will ever see, and that 0.0234 is an upper bound on what a real corpus
|
| 128 |
leaves. For scale, the same eight sentences give multilingual-e5-large a top-1 decision of
|
|
@@ -130,8 +138,13 @@ leaves. For scale, the same eight sentences give multilingual-e5-large a top-1 d
|
|
| 130 |
change what one of the eight queries retrieves.
|
| 131 |
|
| 132 |
So the bar here is half the decision distance rather than all of it, and int8 misses it.
|
| 133 |
-
Correlation reads 0.
|
| 134 |
what says by how much and why.
|
| 135 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
|
| 137 |
(conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))
|
|
|
|
| 76 |
|
| 77 |
## Verification
|
| 78 |
|
| 79 |
+
| build | file | size (MB) | Mac median (ms)* | XNNPACK takes | worst cosine vs eager | retrieval budget spent |
|
| 80 |
+
|---|---|---|---|---|---|---|
|
| 81 |
+
| XNNPACK fp32 | `embed_qwen3_embedding_0_6b_xnnpack_fp32.pte` | 2383.7 | 184.0 | 80.5% | 1.000000 | 0% |
|
| 82 |
+
| XNNPACK fp16 | `embed_qwen3_embedding_0_6b_xnnpack_fp16.pte` | 1192.4 | 521.5 | 70.2% | 0.999992 | 2% |
|
| 83 |
+
| Core ML fp32 | `embed_qwen3_embedding_0_6b_coreml_all.pte` | 1195.1 | **30.0** | 100% | 0.999910 | 17% |
|
| 84 |
|
| 85 |
\*Mac arm64, median of 10, one 256-token sequence — a reference point for relative cost,
|
| 86 |
+
not a device number. Eager fp32 on the same input is 179.7 ms, so the Core ML build is
|
| 87 |
+
**6.0x eager**, 100% delegated in one subgraph.
|
| 88 |
+
|
| 89 |
+
**The XNNPACK column moved because the export stopped going through
|
| 90 |
+
`F.scaled_dot_product_attention`.** It decomposes to `_safe_softmax`, whose guard for
|
| 91 |
+
fully-masked rows is six operations XNNPACK cannot take, once per attention block. This
|
| 92 |
+
model is right-padded, so no query row can lose every key and the guard can never fire:
|
| 93 |
+
with 249 of 256 positions masked, `attn_implementation="eager"` agrees with the sdpa graph
|
| 94 |
+
at cosine 1.00000000 while taking delegation from **71.8% to 80.5%** and fp32 from 203.9 ms
|
| 95 |
+
to 184.0 ms.
|
| 96 |
|
| 97 |
Agreement with eager is the first check and it separates nothing here. The one that decides
|
| 98 |
is the last column: rank all eight test sentences against each other, then ask whether this
|
|
|
|
| 116 |
|
| 117 |
## Not shipped: int8, and this is the first time it was close
|
| 118 |
|
| 119 |
+
**int8 is 1063.9 MB — smaller than fp16's 1192.4 MB.** No other embedding model on this
|
| 120 |
shelf manages that. Dynamic int8 quantises the linear weights and leaves the token
|
| 121 |
embedding table in fp32, so it only wins when that table is a small share of the file, and
|
| 122 |
here it is: 151669 x 1024 = **621 MB of the 2384 MB model, 26%**. Every other embedding
|
|
|
|
| 126 |
different questions:
|
| 127 |
|
| 128 |
```
|
| 129 |
+
worst retrieval score shift 0.0258
|
| 130 |
closest fp32 top-1 decision 0.0234
|
| 131 |
```
|
| 132 |
|
| 133 |
+
The error is **110% of the room available**. On these eight sentences it happens not to
|
| 134 |
change any result — but eight deliberately dissimilar sentences are the friendliest corpus
|
| 135 |
a retrieval model will ever see, and that 0.0234 is an upper bound on what a real corpus
|
| 136 |
leaves. For scale, the same eight sentences give multilingual-e5-large a top-1 decision of
|
|
|
|
| 138 |
change what one of the eight queries retrieves.
|
| 139 |
|
| 140 |
So the bar here is half the decision distance rather than all of it, and int8 misses it.
|
| 141 |
+
Correlation reads 0.990459, which would also have flagged it; the retrieval measurement is
|
| 142 |
what says by how much and why.
|
| 143 |
|
| 144 |
+
The attention rewrite above made int8 **13% faster (174.8 ms to 151.7 ms) and 7 points
|
| 145 |
+
more delegated (77.9% to 85.1%)** and did not change this verdict — it moved the score
|
| 146 |
+
error from 100% of the room to 110%. Speed and quality are separate questions here, and
|
| 147 |
+
only one of them was ever the reason this build is unpublished.
|
| 148 |
+
|
| 149 |
torch.export -> to_edge_transform_and_lower(partitioner) -> .pte
|
| 150 |
(conversion scripts: [executorch-models](https://github.com/john-rocky/executorch-models))
|