iPhone, Android and edge AI
Running a neural network across platforms
iPhones and Android phones can both execute neural networks locally, but the hardware differs. The right approach is therefore not a single accelerator but a shared model strategy with platform-specific inference paths.
The problem: same app idea, different hardware
On iPhone, models typically run through Core ML, Metal/GPU and the Apple Neural Engine. On Android, acceleration depends on the device: Qualcomm Snapdragon can use the Hexagon NPU and Adreno GPU, while other vendors ship their own NPUs and drivers. Add CPU fallbacks, differing Android versions and various runtime APIs.
An app should therefore not assume that "NPU" means the same thing
everywhere. A stable app-level interface is better:
predict(strokes) -> topK labels. Underneath, the
implementation may differ per platform.
Recommended strategy for a small QuickDraw CNN
For DrawLa the task is manageable: strokes are rasterised into a
1 × 96 × 96 image, a CNN computes 345 logits, and the app
shows the most likely words. That model is small enough to run locally on
both mobile platforms.
PyTorch training checkpoint
→ neutral export: ONNX
→ iOS: Core ML / .mlpackage
→ Android: LiteRT or ONNX Runtime Mobile
→ shared app API: predict(strokes)
The core stays identical: the model was trained and tested once. For distribution, however, two or more optimised artefacts are produced. That is normal, and usually better than a minimal solution that runs on both platforms without using either well.
Option A: ONNX Runtime Mobile as the common denominator
ONNX Runtime Mobile executes ONNX models on iOS and Android alike. Attractive if you want to keep one model format. For a small CNN, ONNX is especially natural because the operators are simple: convolutions, normalisation, activation, pooling and a linear layer.
Upside: one neutral export path out of PyTorch, one runtime family for both platforms. Downside: maximum hardware acceleration and binary size still have to be tested per platform.
Source: ONNX Runtime Mobile.
Option B: native artefacts for the best platform fit
On iPhone, Core ML is the native route. With coremltools,
PyTorch models convert directly into Core ML formats. Apple can then
deploy CPU, GPU and Neural Engine as appropriate, provided the model and
its operators are suitable.
On Android, LiteRT or ONNX Runtime Mobile are the usual paths; for Qualcomm devices, additional SDKs or delegates may be interesting. This variant produces several artefacts but is often the most robust performance strategy in production apps.
Sources: Core ML Tools, LiteRT.
Option C: ExecuTorch for PyTorch-native deployments
ExecuTorch is PyTorch's own route to on-device AI. It targets phones, embedded systems and edge devices, and can appeal to teams that want to keep training, export and deployment inside the PyTorch ecosystem for as long as possible.
For DrawLa, ExecuTorch would be technically plausible, but you would have to weigh the overhead against ONNX Runtime Mobile or Core ML. With a small CNN, the simpler runtime is often the better choice.
Source: ExecuTorch documentation.
The real problem is not the model
Anyone planning such a port regularly underestimates where the work is.
Converting the model is one call to coremltools or an export
to ONNX. Preprocessing is the hard part.
In DrawLa the rasteriser currently lives in Python: determine the bounding box, centre, scale with an eight per cent margin, draw segments two pixels wide. On device, the same procedure would have to exist in Dart, Swift or Kotlin — and be pixel-identical.
This is exactly where errors nobody notices are born. If one language rounds differently, a margin is off by a pixel, or line drawing interpolates slightly differently, the model receives inputs it never saw during training. It does not crash and reports no error — it simply gets worse. Without a comparison against the server implementation, that can go unnoticed for months.
Rule of thumb: for every line of model conversion, budget ten lines of preprocessing tests.
How to guarantee parity
The tool for this is reference fixtures. Pick a handful of drawings, store the server-rasterised image and the resulting probabilities for each, and ship both as test data with the app.
fixtures/
cat_01.strokes.json # input
cat_01.raster.png # expected 96×96 image
cat_01.logits.json # expected output
The test on each platform then checks two things separately: does the rasterised image match the reference exactly? And are the outputs within a small tolerance — somewhat more generous for quantised models than for fp32?
The separation matters. If only the output differs, model conversion or quantisation is responsible. If the image already differs, preprocessing is at fault — and any search inside the model is wasted time.
The Flutter detour
DrawLa is written in Flutter, which adds a layer usually missing from platform-neutral discussions: Dart cannot address Core ML or LiteRT directly. The call goes either through a platform channel into native Swift or Kotlin code, or via FFI into a C library.
Both have a cost. A platform channel serialises the data on every call — not dramatic at eight times per second, but not nothing either, and it means maintaining native code for two platforms. FFI avoids the serialisation but demands a C interface and careful memory handling.
For a Flutter app this shifts the balance noticeably towards ONNX Runtime Mobile: one model format, one integration, one set of tests. The last percentage point of hardware acceleration that Core ML would additionally extract does not justify double the integration effort at a model size of two megabytes.
A pragmatic target architecture
The cleanest architecture separates three things: training, model artefacts and the app interface. Training stays in PyTorch. The export produces tested artefacts for iOS and Android. The app itself knows only a small inference interface and need not care whether Core ML, ONNX Runtime or LiteRT sits underneath.
shared Dart/Swift/Kotlin API
rasterize(strokes) -> Float32/UInt8 tensor
predict(tensor) -> topK labels
iOS backend
Core ML model
Android backend
ONNX Runtime Mobile or LiteRT model
This keeps the product logic cross-platform while each platform uses its best inference path. For fast sketch recognition that usually matters more than a single framework that can do everything on paper.
Whether the move on device is worth it at all is discussed in Mobile & Edge AI; the model itself is described in QuickDraw with PyTorch.