Repository navigation
Conversation
The cache key covers the generated source and the gt4py version, not the toolchain that compiles it (C++/CUDA compilers, DaCe, GridTools, nanobind, Python, machine, CUDAARCHS). After a toolchain change a persistent cache would silently reuse binaries built by the old one. A persistent cache now records its toolchain in toolchain.json on first use; every process compares it before compiling into or loading from the cache and raises BuildCacheToolchainError on a difference. GT4PY_BUILD_CACHE_TOOLCHAIN_CHECK=warn downgrades this to a warning (for changes that need no rebuild), =off disables it. Entries the record lacks are added, not compared, so CPU and GPU builds can share a cache. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
In my view the toolchain configuration is a property of the backend not a global one (for gpu the gpu compiler version matters, for cpu only the regular one). The backend instance contributes to the fingerprint of a program / field operator so adding the info there would result in a different path in the cache directory. Not a direct replacement for the proposal here as it would silently rebuild on a toolchain change, but a production run should be done with |
|
Can you explain your use-case? It's hard/impossible to get this right, but maybe a partial solution is good enough for your use-case. |
…er-backend key, see GridTools#2943) Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The cache folder of a compiled program depends on its generated source, the GT4Py version and the build settings, but not on the toolchain that compiles it. After a compiler, device architecture or library change a persistent cache reused binaries built by the old toolchain. The C++ (GTFN) and DaCe compile steps now fold a toolchain fingerprint into the build context id they already compute: machine, Python and the C++ compiler; for device code also the CUDA/HIP compiler and the device architecture; gridtools-cpp and nanobind for C++ programs, dace for DaCe. A toolchain change therefore leads to a new cache folder and a rebuild. The description is computed once per process per language. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Every GTFN program's build script is instantiated from the compile commands of one CMake-configured prototype, keyed by dependencies, build type and CMake flags only. After a change of CXX/CUDACXX to another executable, the new program folders were still built with the compiler the prototype was configured with. The prototype name now carries the toolchain fingerprint. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Description
A persistent build-cache folder is keyed on the program, the fingerprint of the generated source,
BUILD_CACHE_VERSION_ID(default:gt4py.__version__) and the build context (non-default DaCeconfig). The toolchain is not part of the key: after a change of compiler, CUDA, DaCe, GridTools
or Python, a shared persistent cache silently reuses binaries built by the old toolchain.
This PR records the toolchain in the cache and checks it:
config.py:BuildCacheToolchainCheck(ERROR,WARN,OFF) andBUILD_CACHE_TOOLCHAIN_CHECK,set via
GT4PY_BUILD_CACHE_TOOLCHAIN_CHECK=error|warn|off(defaulterror).otf/compilation/cache.py:current_toolchain(),check_build_cache_toolchain(base_path)(cached per process),
BuildCacheToolchainError,TOOLCHAIN_FILE_NAME = "toolchain.json".get_cache_foldercalls the check for thePERSISTENTlifetime only; session caches are unchanged.machine,python, versions ofdace,gridtools-cpp,nanobind(if installed),cxx(first line of$CXX --version, defaultc++),cuda_cxx(the "release" line of$CUDACXX --version, defaultnvcc, only if found),cuda_archs($CUDAARCHS, if set).<cache>/toolchain.jsonunder a file lock (gt4py._core.locking). Later usescompare only keys present in both the record and the current toolchain; keys missing from the
record are added, so CPU and GPU builds can share one cache.
errorraisesBuildCacheToolchainErrorlisting old -> new values and theremedies (delete the cache, use another
GT4PY_BUILD_CACHE_DIR, or setwarn);warnwarns onceper process;
offneither records nor checks.test_cache.py.Why only in
get_cache_folder: every compile path goes through it (genericcompiler.py, theCMake and compiledb build systems, DaCe
workflow/compilation.py), each taking a per-program lockright after. The translation-cache path is resolved when a backend object is built, possibly at
import time, so the check is deliberately not in
get_cache_base_path.Cost (measured on a GH200 node, aarch64): 5-7 ms once per process (two
--versionsubprocesses,three metadata lookups, lock + JSON), ~140 ns for later calls. It never runs on calls of an already
loaded program.
Tested: locally (x86_64, CPU only):
test_cache.py17 passed (9 existing + 8 new);nox -s "test_next-3.12(internal, cpu, nomesh)"4881 passed, 119 skipped, 606 xfailed (+ 111passed, 2 skipped);
nox -s "test_next-3.12(dace, cpu, nomesh)"1495 passed, 25 skipped, 64 xfailed(+ 111 passed, 2 skipped); GPU and atlas sessions not run;
pre-commitclean. Also an end-to-end application run with a fresh persistent cacheon GH200:
toolchain.jsonwritten, no message, results bit-identical to the reference run. A mismatchhas so far only been exercised by the unit tests.
Open questions for reviewers
errororwarn? Existing caches are not broken (a cache without a record just getsone), but after a toolchain change users get an error instead of today's silent reuse.
HIPCXX,HIPARCHS),cmake/ninjaversions, CuPy,compiler flags from the environment, and the device architecture when
CUDAARCHSis unset (Iavoided querying the device here). Should this reuse
otf/compilation/common.py:get_device_arch()?BUILD_CACHE_VERSION_ID. That avoidsstale reuse automatically, but recompiles silently and leaves old folders behind; I preferred an
explicit stop that can be downgraded to a warning.
toolchain.jsonand its lock file sit in the cache root next to the program folders; tools thatlist the cache (e.g. users of
CACHE_FOLDER_NAME_PATTERN) must ignore non-matching entries.Requirements
If this PR contains code authored by new contributors please make sure:
AUTHORS.mdfile adding the names of all the new contributors.🤖 Generated with Claude Code