PlacementSummary
PlacementSummary(placements: list[tuple[str, str]], precision: str = '', units: ComputeUnits | None = None)Where a model's operations are scheduled.
const operations carry no device assignment — they are data, not
computation — so they are counted separately and kept out of the
fraction. Reporting 21% ANE for a model whose every computation runs
on the ANE would be true of the raw operation list and useless.
Examples
>>> import shutil, tempfile
>>> import lucid, lucid.nn as nn, lucid.coreml as cml
>>> model = nn.Sequential(nn.Conv2d(3, 16, 3, padding=1), nn.ReLU()).eval()
>>> x, room = lucid.randn(1, 3, 32, 32), tempfile.mkdtemp()
>>> package = cml.export(model, x, f"{room}/half.mlpackage",
... precision=cml.Precision.FLOAT16,
... compute_units=cml.ComputeUnits.CPU_ONLY)
>>> plan = package.compute_plan()
>>> plan.constants > 0 and plan.total_compute > 0 # counted apart
True
>>> plan.note # the CPU was asked for: nothing to say
''
A float32 program asked for the Neural Engine is the case it speaks up
for, since that device does not run float32:
>>> single = cml.export(model, x, f"{room}/single.mlpackage",
... compute_units=cml.ComputeUnits.CPU_AND_NE)
>>> single.compute_plan().ane_fraction
0.0
>>> print(single.compute_plan().note)
no operation reached the Neural Engine because the program is float32, ...
>>> package.close()
>>> single.close()
>>> shutil.rmtree(room)Used by 1
Constructors
1Properties
3Share of computation the Neural Engine takes, 0.0 to 1.0.
0.0 on a model asked to use the ANE is the signal that the
request did not take — most often because the program is float32,
which the Neural Engine does not run.
Why the Neural Engine took none of the work, when it took none.
A float32 program cannot run on the Neural Engine at all — it is a float16 device — so an export that keeps the default precision lands entirely on the CPU however the compute units were asked for. Measured on a ResNet-18: 66 of 66 operations on the CPU at float32, 66 of 68 on the Neural Engine at float16.
Nothing about that is an error, and Core ML reports no problem, so the only place it can surface is here — where somebody is already asking where the work went.
The float32 explanation is given only for a program known to be float32. A float16 one that still lands elsewhere has another cause, and so may a package that does not record its precision — one Lucid did not write, or wrote before it recorded one — so those get the causes Core ML leaves unsaid instead of advice that would send the reader to a setting they already have.