JFJochReceiverService::Indexing: kept FFT indexers of the old settings are released

Since 0df766328 the broker keeps an FFTIndexerReuse for its whole life, so the broker's own indexing
pool (Lite and FPGA receivers) hands its GPU FFT indexers back to the reuse cache instead of freeing
them. The cache is keyed on the FFT settings and never shrank: every change of the indexing settings
through the API parked another 0.6-0.9 GB per worker on the card, until a pool build ran out of GPU
memory. (Before 0df766328 the same happened from the first live rotation run on.) The service now
releases the kept indexers when it rebuilds the pool; rugnux live keeps new ones at its next run.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK
This commit is contained in:
leonarski_fandClaude Opus 5.5 committed 2026-11-08 09:51:04 +01:00
1 parent ae4fa109ec
commit 8f47fb756b
4 files changed
+21

No files matched your search

@@ -59,6 +59,7 @@ FFTPlanReuse::~FFTPlanReuse() = default;
FFTIndexerReuse::FFTIndexerReuse() = default;
FFTIndexerReuse::~FFTIndexerReuse() = default;
void KeepFFTIndexers(const IndexingSettings &, int) {}
void ReleaseKeptFFTIndexers() {}
#endif
#ifdef JFJOCH_USE_CUDA
@@ -152,6 +153,18 @@ static std::unique_ptr<Indexer> MakeFFTIndexerGPU(const IndexingSettings &settin
return std::make_unique<FFTIndexerGPU>(settings);
}
void ReleaseKeptFFTIndexers() {
std::map<FFTIndexerKey, std::vector<std::unique_ptr<Indexer>>> idle;
{
std::lock_guard lock(kept_fft_indexers().m);
idle.swap(kept_fft_indexers().idle);
}
for (auto &[key, list] : idle) {
ScopedGpuPin pin(std::get<0>(key));
list.clear();
}
}
void KeepFFTIndexers(const IndexingSettings &settings, int count) {
if (get_gpu_count() == 0)
return;
@@ -74,6 +74,9 @@ public:
// destroyed). Nothing without a GPU.
void KeepFFTIndexers(const IndexingSettings &settings, int count);
// Destroys the kept FFT indexers that no pool is using: a settings change leaves them keyed on the old settings.
void ReleaseKeptFFTIndexers();
class IndexerThread {
struct TaskInput {
const DiffractionExperiment &experiment;
+1
View File
@@ -433,6 +433,7 @@ JFJochReceiverService &JFJochReceiverService::Indexing(const IndexingSettings &i
logger.Info("Resetting indexing thread pool");
indexer_thread_pool.reset();
ReleaseKeptFFTIndexers();
if (input.GetAlgorithm() != IndexingAlgorithmEnum::None) {
logger.Info("Creating indexing thread pool...");
+4
View File
@@ -443,6 +443,10 @@ TEST_CASE("IndexerThreadPool_FFTIndexerKeptAcrossPools", "[CUDAMemHelpers]") {
CHECK(r.lattice.size() == fresh.lattice.size());
}
CHECK(pooled() == kept);
// A settings change in the broker: the kept indexers go while the reuse scope lives on
ReleaseKeptFFTIndexers();
CHECK(pooled() <= before + (uint64_t(16) << 20));
}
CHECK(pooled() <= before + (uint64_t(16) << 20));
for (int d = 0; d < get_gpu_count(); d++) {