Test FP32 Ethos-U delegation
Prepare the MobileNetV2 model used in Module 2, this time for the Ethos-U backend rather than a CPU backend like XNNPACK.
Run on the Linux host:
python module-4-ethos-npu-accelerated-inference/scripts/aot/prepare_mobilenetv2.py \
--out module-4-ethos-npu-accelerated-inference/artifacts/mobilenetv2
The preparation script downloads the same TorchVision MobileNetV2 IMAGENET1K_V1 weights and
public-domain yellow Labrador image used in Module 2, saves a state dict, and
writes ImageNet labels:
weights = MobileNet_V2_Weights.IMAGENET1K_V1
model = mobilenet_v2(weights=weights).eval()
torch.save(model.state_dict(), weights_path)
labels_path.write_text(json.dumps(weights.meta["categories"], indent=2) + "\n")
The script also writes the model input shape and preprocessing settings and creates model_spec.json:
spec = {
"name": "mobilenetv2",
"weights": weights_path.name,
"labels": labels_path.name,
"sample_image": sample_path.name if sample_path.exists() else None,
"input": {
"shape": [1, 3, 224, 224],
"preprocessing": {
"resize": 256,
"center_crop": 224,
"mean": [0.485, 0.456, 0.406],
"std": [0.229, 0.224, 0.225],
},
},
}
The shape [1, 3, 224, 224] is one RGB image in NCHW order: batch, channels,
height, and width. The resize, crop, mean, and standard deviation are the
ImageNet preprocessing values expected by the pre-trained MobileNetV2 model.
Attempt to lower the FP32 model for Ethos-U:
python module-4-ethos-npu-accelerated-inference/scripts/aot/lower_fp32_ethosu.py \
--spec module-4-ethos-npu-accelerated-inference/artifacts/mobilenetv2/model_spec.json \
--target ethos-u85-256 \
--system-config Ethos_U85_SYS_DRAM_Mid \
--memory-mode Shared_Sram
You should expect to see output similar to this:
PTE size: 14.24 MB
Delegation
==========
Ethos-U delegate call sites: 0
Fallback call_function ops: 461
Selected non-delegated operators:
aten._native_batch_norm_legit_no_training.out (52)
aten.add.out (10)
aten.addmm.out (1)
aten.convolution.out (52)
aten.hardtanh.out (35)
aten.mean.out (1)
Record the results you obtain:
| Item | Result, and what it means |
|---|---|
| Ethos-U delegate call sites | |
Fallback call_function operations |
The script writes a .pte artifact, but the delegation summary shows
that no region was handed to Ethos-U. The selected operators show that the
MobileNetV2 convolutions, batch normalization, activations, and classifier
remain outside the Ethos-U delegate. This result is expected. Ethos-U acceleration is designed around
quantized integer workloads. An FP32 .pte artifact can still be generated,
but no subgraphs are delegated to the NPU. Its operations remain on the default
ExecuTorch path and would require compatible target CPU kernels to run.
Generating the artifact does not prove that it can execute on the FVP; this
module does not run it.
Understand the script
The script follows the same basic export-and-lower pattern used in Module 2.
It reloads the MobileNetV2 weights prepared earlier, creates an example tensor
with the shape from model_spec.json, exports the model, lowers with a backend
partitioner, writes the .pte artifact, and prints a delegation summary.
spec = json.loads(args.spec.read_text())
artifact_dir = args.spec.parent
model = mobilenet_v2(weights=None).eval()
model.load_state_dict(torch.load(artifact_dir / spec["weights"], map_location="cpu"))
example_inputs = (torch.randn(*spec["input"]["shape"]),)
exported = export_no_guards(model, example_inputs)
The main difference from Module 2 is the backend. Module 2 used
XnnpackPartitioner for CPU execution. This script uses an Ethos-U compile
specification and EthosUPartitioner, so the Arm backend can identify regions
that Vela can compile for the selected Ethos-U target.
The lowering stage is:
compile_spec = EthosUCompileSpec(
target=args.target,
system_config=args.system_config,
memory_mode=args.memory_mode,
extra_flags=args.extra_flag,
)
edge = to_edge_transform_and_lower(
exported,
compile_config=EdgeCompileConfig(_check_ir_validity=False),
partitioner=[EthosUPartitioner(compile_spec)],
)
EthosUCompileSpec records the target NPU, system configuration, memory mode,
and Vela options used by the Arm backend. EthosUPartitioner uses this
configuration when identifying regions that can be compiled by Vela. The
partitioner is supplied to the same
to_edge_transform_and_lower() API used with XNNPACK in earlier modules.
The compile specification tells the Arm backend which NPU target, system configuration, and memory mode to use. In this module, the target
is ethos-u85-256, the system configuration is Ethos_U85_SYS_DRAM_Mid, and the memory mode is Shared_Sram.
Course complete
Nice work
You completed Optimize and deploy AI inference with ExecuTorch on Arm.