feat(core): GPU-offload clamp with per-workload floor

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
jars
2026-05-09 11:53:03 +01:00
parent 847dc755ac
commit 6b456b1766

View File

@@ -59,7 +59,13 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
if power::probe_power_state() == PowerState::OnBattery {
chosen /= 2;
}
let _ = (workload, gpu_offloaded); // GPU clamp added in next task
if gpu_offloaded {
let floor = match workload {
Workload::Llm => GPU_FLOOR_LLM,
Workload::Whisper => GPU_FLOOR_WHISPER,
};
chosen = chosen.min(floor);
}
chosen.clamp(MIN_INFERENCE_THREADS, MAX_INFERENCE_THREADS)
}
@@ -128,4 +134,52 @@ mod tests {
}
});
}
#[test]
fn gpu_offload_clamps_llm_to_floor() {
with_thread_env_lock(|| {
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
crate::power::with_override(Some(PowerState::OnAc), || {
let n = inference_thread_count(Workload::Llm, true);
assert!(n <= GPU_FLOOR_LLM.max(MIN_INFERENCE_THREADS),
"Llm with GPU offload should clamp to {GPU_FLOOR_LLM}, got {n}");
assert!(n >= MIN_INFERENCE_THREADS);
});
});
}
#[test]
fn gpu_offload_clamps_whisper_to_floor() {
with_thread_env_lock(|| {
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
crate::power::with_override(Some(PowerState::OnAc), || {
let n = inference_thread_count(Workload::Whisper, true);
// Whisper floor is 4 on machines with >=4 physical cores;
// can't go lower than physical so on a 2c host we stay at 2.
assert!(n <= GPU_FLOOR_WHISPER, "got {n}");
assert!(n >= MIN_INFERENCE_THREADS);
});
});
}
#[test]
fn whisper_gpu_floor_is_at_least_llm_gpu_floor() {
// Architectural invariant: whisper retains CPU work even when
// GPU-offloaded; its floor must not be lower than the LLM's.
assert!(GPU_FLOOR_WHISPER >= GPU_FLOOR_LLM);
}
#[test]
fn gpu_offload_off_does_not_clamp_below_battery_calc() {
with_thread_env_lock(|| {
std::env::remove_var("MAGNOTIA_INFERENCE_THREADS");
// Sequential measurements; with_override is non-reentrant.
crate::power::with_override(Some(PowerState::OnAc), || {
let no_gpu = inference_thread_count(Workload::Llm, false);
let with_gpu = inference_thread_count(Workload::Llm, true);
// GPU-offloaded should be <= non-offloaded.
assert!(with_gpu <= no_gpu);
});
});
}
}