Repository navigation
Commit dadc829
authored
Core ML: run ops on the CPU when Core ML cannot take or return their values (#24317)
## What is wrong today
coremltools cannot take a uint8 or int8 tensor as a Core ML input, such
as camera pixels or int8 tensors in a quantized model. Lowering fails
with `KeyError: torch.uint8`. An input sized by an expression such as
`s0 + 1` fails too, unless the program declares it.
Some values cannot leave Core ML either: the delegate has no int8 data
type and returns only tensors, so neither an int8 tensor nor a symbolic
value, such as a size, can be an output.
`ops_to_not_decompose` can also keep an op whole that then runs on the
CPU, where the portable kernels may lack it, such as the matmul of a
bfloat16 linear.
`zeros_like` and `fill` put a constant as big as their input into the
model when its shape is known, and since #24424 `ones_like` and
`full_like` do too.
## What this change does
- The partitioner leaves on the CPU each op that reads such a tensor, or
a symbolic value computed on the CPU, from outside its partition, and
each op that makes an int8 tensor or a symbolic value used outside its
partition. Weights, constants and state that Core ML takes over are not
inputs. The search repeats as ops move out, and partitions left reading
only sizes, or nothing below iOS 18, move out too.
- State stays in the program when no op reads it, or when a CPU op or a
second partition also uses it or the model returns its new value. An op
that reads such uint8 or int8 state, or makes its new int8 value, moves
to the CPU.
- With `lower_full_graph=True`, a Core ML part that would return an int8
tensor now fails while lowering, with the reason, not at run time.
- `ops_to_not_decompose` stops keeping an op whole when the partitioner
moves some call of it to the CPU, or when Core ML rejects a call that
decomposing makes. It decomposes the program as lowering will only when
that may change the answer.
- From iOS 16, those four fills use Core ML's `fill_like` instead.
- The docs list the values Core ML cannot take or return, and point
camera apps to the `ImageProcessor` in `extension/image`.
## Testing
- `test_coreml_partitioner.py`, `test_torch_ops.py` and
`test_coreml_recipes.py` pass on Linux and macOS, where most new tests
also compare outputs with eager PyTorch.
- Most new tests fail on main.1 parent 5e8d11b commit dadc829
5 files changed
Lines changed: 1828 additions & 44 deletions
File tree
- backends/apple/coreml
- compiler
- partition
- test
- docs/source/backends/coreml
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
13 | 13 | | |
14 | 14 | | |
15 | 15 | | |
16 | | - | |
| 16 | + | |
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
| |||
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
34 | 37 | | |
35 | 38 | | |
36 | 39 | | |
| |||
92 | 95 | | |
93 | 96 | | |
94 | 97 | | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
95 | 108 | | |
96 | 109 | | |
97 | 110 | | |
| |||
119 | 132 | | |
120 | 133 | | |
121 | 134 | | |
122 | | - | |
| 135 | + | |
123 | 136 | | |
124 | 137 | | |
125 | 138 | | |
| |||
153 | 166 | | |
154 | 167 | | |
155 | 168 | | |
156 | | - | |
| 169 | + | |
157 | 170 | | |
158 | 171 | | |
159 | 172 | | |
160 | 173 | | |
161 | 174 | | |
162 | 175 | | |
163 | 176 | | |
164 | | - | |
| 177 | + | |
165 | 178 | | |
166 | 179 | | |
167 | 180 | | |
| |||
0 commit comments