Numba linker: fgraph_to_python puts fgraph inputs in global_env, preventing numba caching
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 78/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- numpy, python
- Ambito
- backend, performance
Direzione di ricerca
Inizia in pytensor/link/utils.py, presso fgraph_to_python, e verifica come gli input dei nodi vengono aggiunti a global_env. Esegui il reproducer fornito per FunctionGraph e numba, quindi verifica che gli input delle funzioni non vengano mantenuti come globali di grandi dimensioni e che l’avviso Cannot cache non compaia più.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Numba linker: fgraph_to_python puts fgraph inputs in global_env, preventing numba caching
Description
When compiling a FunctionGraph with the numba linker, fgraph_to_python
(populates global_env with all non-None storage values, including
variables that are already fgraph.inputs (function parameters). This
means the generated Python function has large array constants in its
__globals__ dict, which numba's CacheImpl.check_cachable rejects as
"dynamic globals (such as ctypes pointers and large global arrays)".
The result: numba cannot cache the compiled artifact, and every fresh
process pays the full JIT cost (~165s for a 30-layer transformer on
Apple M3 Max).
Reproducer
import warnings
import numpy as np
import pytensor
import pytensor.tensor as pt
from pytensor.graph.basic import graph_inputs
from pytensor.compile.sharedvalue import SharedVariable
import pytensor_ml.pytensorf as pytensorf
# Build a graph with shared variable weights
W = pytensor.shared(np.random.randn(64, 64).astype("float32"), name="W")
x = pt.matrix("x")
y = pt.dot(x, W)
# Compile with numba
fn = pytensor.function([x], y, mode="NUMBA")
# Run to trigger JIT
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always")
fn(np.ones((1, 64), dtype="float32"))
cache_warnings = [x for x in w if "Cannot cache" in str(x.message)]
print(f"Cannot-cache warnings: {len(cache_warnings)}")
for cw in cache_warnings:
print(f" {cw.message}")
On pytensor 3.3.2 with numba 0.67.0, this prints:
Cannot-cache warnings: 1
Cannot cache compiled function "numba_funcified_fgraph" as it uses dynamic globals
(such as ctypes pointers and large global arrays)
Root cause
In pytensor/link/utils.py, fgraph_to_python:
for node in order:
for inp in node.inputs:
is_constant = isinstance(inp, Constant)
input_storage = storage_map.setdefault(
inp, [inp.data if isinstance(inp, Constant) else None])
if (is_constant or input_storage[0] is not None) and inp not in tipifiyed_vars:
global_env[local_input_name] = type_conversion_fn(
input_storage[0], variable=inp, storage=input_storage, **kwargs)
tipifiyed_vars.add(inp)
When a shared variable's value is not None (always true for loaded weights),
it gets placed in global_env even if it's also a fgraph.input. The
generated function then has both the variable as a parameter AND as a global.
For a model like SmolLM2-135M-Instruct (30 layers, 272 weight variables),
this means 332 large array globals (~400MB) in the function's __globals__.
Proposed fix
Skip fgraph inputs from global_env:
# In fgraph_to_python, change:
if (is_constant or input_storage[0] is not None) and inp not in tipifiyed_vars:
# To:
if (is_constant or input_storage[0] is not None) and inp not in tipifiyed_vars and inp not in set(fgraph.inputs):
This is a ~3-line change that makes the generated function only reference
non-input constants in its globals, allowing numba to cache the compiled
artifact.
Impact
For SmolLM2-135M-Instruct on Apple M3 Max:
- Before fix: Every
load_llmpays ~165s of numba JIT (5 outer function
compiles × ~33s each). The 85k entries in~/.pytensor/numba/are for
per-op inner graphs, not the expensive outer functions. - After fix: The outer functions become cacheable. First process pays
~165s; subsequent processes load from numba's disk cache in seconds.
The per-op inner graphs (numba_ofg, 124 compiles, ~44s total) are a
separate, smaller cost that may also benefit from this fix if they have
the same issue.
Environment
- pytensor: 3.3.2
- numba: 0.67.0
- Python: 3.12.13
- macOS 26 / arm64 (Apple M3 Max)
- Lingua principale
- Python
- Stelle
- 648
- Fork
- 227
- Merge medio
- 3g 3h
- PR unite (30g)
- 41
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di pymc-devs/pytensor
-
bug mlx
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Reciprocal.impl computes np.float32(1.0) / x: float32 precision for float64 scalars under NEP 50 (Python linker)Forse già presa @Ai-Eastern l’ha presa 30 giorni fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
pymc-devs/pytensor#2430 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
pymc-devs/pytensor#2330 · 3 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
pymc-devs/pytensor#2329 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di pymc-devs/pytensor
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
MISP/misp-workbench#496 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 88/100
fossasia/visdom-dev#69 ·
I maintainer di solito rispondono entro 3 giorni
-
[Bug] Parameters named like a property break to_xcal()Forse già presa @atharvasalunke1267 l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
collective/icalendar#2018 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
I maintainer di solito rispondono entro 1 giorno