// SPDX-FileCopyrightText: 2026 Filip Leonarski, Paul Scherrer Institute // SPDX-License-Identifier: GPL-3.0-only #pragma once #include #include "Logger.h" // cuFFT ships its transforms as PTX (cuFFT 11 and 12 alike, for every card), so every plan it makes has // the driver compile kernels - and makes them again for a second plan of the same shape. The driver keeps // what it compiled in its JIT cache, CUDA_CACHE_PATH or else $HOME/.nv/ComputeCache: from there a plan // takes about 1 ms, without it 60-130 ms, all under cuFFT's process-wide lock. A run that makes a hundred // plans (molecular replacement) is then seconds slower, with nothing else to show for it. struct CudaJitCache { std::string path; // where the driver keeps it; empty when it keeps none std::string filesystem; // the type of the filesystem it is on (Linux only) std::string problem; // why the driver cannot use it, or only slowly; empty when none is seen }; CudaJitCache InspectCudaJitCache(); // Where the driver would keep no usable cache - typically a service run as root by systemd without User=, // so with no HOME - and CUDA_CACHE_PATH is not set, point CUDA_CACHE_PATH at a directory of this user's // own, /var/tmp/jfjoch-cuda-cache- (0700). The driver reads it once, when it initialises, so this // must run before anything touches CUDA. Linux only; a CUDA_CACHE_PATH set by the site is left alone. void UsePrivateCudaJitCacheIfNeeded(); // One line for a program's start: the cache, and `plan_ms` - how long one cuFFT plan took to make once // cuFFT was initialised (WarmUpCuFFT). A warning, saying what to do, when the cache is unusable or a plan // is slow. Nothing when plan_ms is NaN: there is no GPU, so no cuFFT. void LogCudaJitCache(Logger &logger, double plan_ms);