GPU memory over the run: FFT indexers given back after the last indexing; speculative probe takes turns with the merge on a small card
- IndexerThreadPool::ReleaseIndexers(): each worker drops the indexers it has built (once its current frame is done) and the allocation pool is trimmed, so their memory goes back to the card, not only to the pool. A later frame builds them again, as on first use. A rotation pass calls it once its first pass is done and again when the leftover-lattice census - the last of its indexing - ends. Measured on the RTX 5080: the 1.24 GB (pre-pass) / 0.62 GB (later passes) the pass's pool held through the image pass and the scaling is gone; 4nwv's pre-pass image pass peaks 5.97 instead of 7.18 GB of device memory. - GPUMerge: the main line holds one through ScaleMergeAndSymmetry. The speculative geometry probe (GPUWorkBeside(after_merges=true)) waits for it on a card below the take-turns size (12 GB), where the probe's FFT indexers and image workers beside the merge's arrays would overfill the card - on a Windows (WDDM) card that does not fail an allocation but pages it and crawls. The merge waits for nothing, so nothing the merge waits on (the rotation-scale walk's probes) can wait in a circle with it. No change on a 16 GB card. Output unchanged: p.hkl byte-identical on cytc_x10sa, myob_x10sa, 4nwv and 8qaw on this card; also identical with the card's total read as 8.55 GB (10 / 9 image workers instead of 16) and with 4 image workers, so the worker count does not change the result. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
640b2e464a
commit
1c3a2e202c
7 files changed
+174
-10
No files matched your search
+14
-3
@@ -33,7 +33,7 @@ namespace {
|
||||
// thread to wait until none of one kind is.
|
||||
std::mutex gpu_work_m;
|
||||
std::condition_variable gpu_work_changed;
|
||||
int gpu_work_beside_n = 0, gpu_image_passes_n = 0;
|
||||
int gpu_work_beside_n = 0, gpu_image_passes_n = 0, gpu_merges_n = 0;
|
||||
|
||||
// A card too small for a probe pass beside the main line's image pass, or beside another probe pass:
|
||||
// measured on a 16 Mpx detector, two of them together held 8.6 GB. On such a card a probe pass waits,
|
||||
@@ -56,10 +56,12 @@ namespace {
|
||||
}
|
||||
}
|
||||
|
||||
GPUWorkBeside::GPUWorkBeside() {
|
||||
GPUWorkBeside::GPUWorkBeside(bool after_merges) {
|
||||
std::unique_lock lock(gpu_work_m);
|
||||
if (take_turns())
|
||||
gpu_work_changed.wait(lock, [] { return gpu_image_passes_n == 0 && gpu_work_beside_n == 0; });
|
||||
gpu_work_changed.wait(lock, [after_merges] {
|
||||
return gpu_image_passes_n == 0 && gpu_work_beside_n == 0 && (!after_merges || gpu_merges_n == 0);
|
||||
});
|
||||
++gpu_work_beside_n;
|
||||
}
|
||||
|
||||
@@ -83,6 +85,15 @@ GPUImagePass::~GPUImagePass() {
|
||||
remove(gpu_image_passes_n);
|
||||
}
|
||||
|
||||
GPUMerge::GPUMerge() {
|
||||
std::lock_guard lock(gpu_work_m);
|
||||
++gpu_merges_n;
|
||||
}
|
||||
|
||||
GPUMerge::~GPUMerge() {
|
||||
remove(gpu_merges_n);
|
||||
}
|
||||
|
||||
void wait_for_gpu_image_passes() {
|
||||
std::unique_lock lock(gpu_work_m);
|
||||
gpu_work_changed.wait(lock, [] { return gpu_image_passes_n == 0; });
|
||||
|
||||
Reference in new issue
Block a user