GPU or CPU decided up front from the card's total memory, never from what is free
- Scaling: the 80%-of-card check runs right after the device ingest's sort and cut, where the observation and distinct-hkl counts are first known, instead of after the geometry smoothing; same counts, same decision, but a run that goes to the CPU no longer does the device smoothing (6.9 s on an 8 GB card for a 33 M observation set) or holds its memory meanwhile. - Rigid body: engines budgeted on a quarter of the card's total (the validation's plan), not min(total/4, free - 1 GB). A busy card no longer sends the rigid body to the CPU (measured on an 8 GB card: ~80 s and a different fit); engine allocations wait for GPU work beside the run, and an engine that cannot be set up fails the validation (RigidBodyGPUFailure) instead of falling back to the CPU. - Beam-centre FFT: GPU when its footprint is at most half of the card's total, otherwise CPU, logged; no catch-and-rescore on the CPU after a GPU failure. - FitPerFrameG reserves its per-frame vector (CPU scaling waited on the heap lock on Windows). - get_gpu_free_memory(): cudaMemGetInfo, except on an integrated GPU under Linux, where free also counts MemAvailable less a tenth of the total. Used only where free memory is waited on (cuda_memory_available) or quoted in out-of-memory messages; it decides nothing. The two card-filling [CUDAMemHelpers] tests skip on integrated GPUs. - Out-of-memory messages point at rugnux --no-gpu instead of "the CPU build". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1182,18 +1182,11 @@ TEST_CASE("ModelValidation_RigidBodyTranslationDerivativeIsExact", "[ModelValida
|
||||
|
||||
#ifdef JFJOCH_USE_CUDA
|
||||
namespace {
|
||||
// A pool of `engines`, or a SKIP where there is none because the card is busy - over half its memory
|
||||
// taken by something else, where the pool falls back to the CPU by design. Anywhere else no pool fails.
|
||||
// A pool of `engines`: decided on the card's total memory, so there is one wherever there is a GPU.
|
||||
std::unique_ptr<RigidBodyGPUPool> TestPool(const gemmi::Model &model, const gemmi::UnitCell &cell,
|
||||
const gemmi::SpaceGroup &sg, double d_min, size_t observations,
|
||||
size_t engines, Logger &logger) {
|
||||
auto pool = RigidBodyGPUPool::Create(model, cell, sg, d_min, observations, engines, logger);
|
||||
if (!pool) {
|
||||
size_t free = 0, total = 0;
|
||||
RigidBodyGPUEngine::MemoryInfo(free, total);
|
||||
if (free < total / 2)
|
||||
SKIP("No GPU engine: the card is busy (" << free / 1000000 << " of " << total / 1000000 << " MB free)");
|
||||
}
|
||||
REQUIRE(pool);
|
||||
return pool;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user