Remove the compiled models Lucid keeps for packages it has loaded.
Core ML runs a compiled model, and loading one makes Core ML write a specialised bundle — for a GPU segment, a full copy of the weights — into its own cache, keyed by where the compiled model is. So Lucid compiles each package once, keeps the compiled model, and opens that same one on every later load; the bundle is then read again rather than written again. Before, every load compiled to a fresh path and left Core ML a bundle nothing would read: a development machine's cache reached 121 GB.
The kept models live in a versioned directory (v1) under
LUCID_COREML_CACHE_DIR — by default $LUCID_HOME/coreml or
~/.cache/lucid/coreml — and keep to LUCID_COREML_CACHE_LIMIT
bytes (4G unless set; 0 turns the cache off), dropping the
least recently used first. This empties it now. A model an open
handle holds, in this process or another, stays, and so does anything
in the directory that Lucid did not put there.
The bundles Core ML made from the removed models stay in Core ML's own cache, which macOS purges when the disk runs low; a package loaded again after this is compiled again and gets a new one.
Returns
intBytes freed.
Examples
>>> import os, shutil, tempfile
>>> import lucid, lucid.nn as nn, lucid.coreml as cml
>>> room = tempfile.mkdtemp()
>>> saved = os.environ.get("LUCID_COREML_CACHE_DIR")
>>> os.environ["LUCID_COREML_CACHE_DIR"] = f"{room}/cache" # one of its own
>>> model = nn.Sequential(nn.Conv2d(3, 8, 3), nn.ReLU()).eval()
>>> x = lucid.randn(1, 3, 16, 16)
>>> cml.export(model, x, f"{room}/m.mlpackage").close() # compiles, keeps it
>>> with cml.load(f"{room}/m.mlpackage") as again: # opens the kept one
... print(again.predict(x).shape)
(1, 8, 14, 14)
>>> cml.empty_cache() > 0
True
>>> cml.empty_cache() # nothing left
0
>>> if saved is None:
... del os.environ["LUCID_COREML_CACHE_DIR"]
... else:
... os.environ["LUCID_COREML_CACHE_DIR"] = saved
>>> shutil.rmtree(room)