feat(core): GPU-offload clamp with per-workload floor
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -59,7 +59,13 @@ pub fn inference_thread_count(workload: Workload, gpu_offloaded: bool) -> usize
|
|||||||
if power::probe_power_state() == PowerState::OnBattery {
|
if power::probe_power_state() == PowerState::OnBattery {
|
||||||
chosen /= 2;
|
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)
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user