Summary
import openequivariance (v0.4.1) JIT-builds two torch extensions at import time in openequivariance/extlib/__init__.py:
torch_module = torch.utils.cpp_extension.load("libtorch_tp_jit", ...)
generic_module = torch.utils.cpp_extension.load("generic_module", ...)
torch.utils.cpp_extension.load has two properties that combine badly on shared/limited hosts:
- ninja parallelism defaults to
nproc (only bounded by the MAX_JOBS env var), and
- concurrent/subsequent builds serialize on a
lock file in the extension build dir via torch's FileBaton, which spin-waits indefinitely with no timeout.
If a first build is killed part-way (OOM-killer, cgroup pids limit, user Ctrl-C, batch scheduler), the stale lock file remains, and every later import openequivariance hangs forever, silently — no traceback, no log, nothing on the GPU.
Observed in the field
On a login node with a per-user cgroup pids.max=100 (Fedora 36, RTX A4500, torch 2.x cu128, openequivariance 0.4.1, installed as the enable_OpenEquivariance modifier path of nequip-compile):
- the first import's ninja swarm (
-j <nproc>) exceeded the pids limit and died;
- the stale
lock remained in ~/.cache/torch_extensions/<tag>/libtorch_tp_jit/;
- every subsequent
nequip-compile ... --modifiers enable_OpenEquivariance then hung deterministically at model load, reproducibly, with zero diagnostics.
The same workload with prebuilt-kernel backends (cuEquivariance) on the same host was unaffected, which is what isolated the JIT path.
Suggested fixes (any of these would prevent the silent hang)
- Wrap the two
cpp_extension.load calls with a bounded wait: if the baton does not clear within N minutes, raise with a message naming the lock path instead of spinning forever.
- Detect a stale lock proactively (lock exists but no live ninja/compiler process) and remove it before building.
- Default
MAX_JOBS to a small value (e.g. 4) for these two import-time builds unless the user overrides — an import-time side effect should not fan out to nproc compile jobs.
- At minimum, document
MAX_JOBS and the stale-lock failure mode in the install docs.
Our downstream workaround (for reference): set MAX_JOBS=4 for any process importing oeq, and pre-clean libtorch_tp_jit/lock + generic_module/lock under $TORCH_EXTENSIONS_DIR when no ninja process is alive.
Thanks for the great kernels — happy to test a patch.
Summary
import openequivariance(v0.4.1) JIT-builds two torch extensions at import time inopenequivariance/extlib/__init__.py:torch.utils.cpp_extension.loadhas two properties that combine badly on shared/limited hosts:nproc(only bounded by theMAX_JOBSenv var), andlockfile in the extension build dir via torch'sFileBaton, which spin-waits indefinitely with no timeout.If a first build is killed part-way (OOM-killer, cgroup pids limit, user Ctrl-C, batch scheduler), the stale
lockfile remains, and every laterimport openequivariancehangs forever, silently — no traceback, no log, nothing on the GPU.Observed in the field
On a login node with a per-user cgroup
pids.max=100(Fedora 36, RTX A4500, torch 2.x cu128, openequivariance 0.4.1, installed as theenable_OpenEquivariancemodifier path ofnequip-compile):-j <nproc>) exceeded the pids limit and died;lockremained in~/.cache/torch_extensions/<tag>/libtorch_tp_jit/;nequip-compile ... --modifiers enable_OpenEquivariancethen hung deterministically at model load, reproducibly, with zero diagnostics.The same workload with prebuilt-kernel backends (cuEquivariance) on the same host was unaffected, which is what isolated the JIT path.
Suggested fixes (any of these would prevent the silent hang)
cpp_extension.loadcalls with a bounded wait: if the baton does not clear within N minutes, raise with a message naming the lock path instead of spinning forever.MAX_JOBSto a small value (e.g. 4) for these two import-time builds unless the user overrides — an import-time side effect should not fan out tonproccompile jobs.MAX_JOBSand the stale-lock failure mode in the install docs.Our downstream workaround (for reference): set
MAX_JOBS=4for any process importing oeq, and pre-cleanlibtorch_tp_jit/lock+generic_module/lockunder$TORCH_EXTENSIONS_DIRwhen no ninja process is alive.Thanks for the great kernels — happy to test a patch.