fix(hwfit): normalize CPU arch for fallback estimates (#4441)

This commit is contained in:
RaresKeY
2026-06-18 20:26:22 +02:00
committed by GitHub
parent b51d83b16d
commit 16e660ad09
5 changed files with 119 additions and 10 deletions
+55
View File
@@ -0,0 +1,55 @@
"""CPU architecture normalization for HW Fit hardware detection."""
import pytest
from services.hwfit import hardware
@pytest.fixture(autouse=True)
def _clear_hwfit_cache(monkeypatch):
hardware._cache_by_host.clear()
monkeypatch.setattr(hardware, "_remote_host", None)
monkeypatch.setattr(hardware, "_remote_platform", None)
monkeypatch.setattr(hardware, "_is_containerized", lambda: False)
yield
hardware._cache_by_host.clear()
def _stub_common_probe(monkeypatch, machine):
monkeypatch.setattr(hardware.platform, "machine", lambda: machine)
monkeypatch.setattr(hardware, "_get_ram_gb", lambda: 64.0)
monkeypatch.setattr(hardware, "_get_available_ram_gb", lambda: 48.0)
monkeypatch.setattr(hardware, "_get_cpu_count", lambda: 16)
monkeypatch.setattr(hardware, "_get_cpu_name", lambda: "Test CPU")
monkeypatch.setattr(hardware, "_detect_apple_silicon", lambda: None)
monkeypatch.setattr(hardware, "_detect_amd", lambda: None)
def test_detect_system_reports_cpu_arch_for_gpu_backends(monkeypatch):
"""GPU-backed systems still need CPU architecture for cpu_only estimates."""
_stub_common_probe(monkeypatch, "aarch64")
monkeypatch.setattr(hardware, "_detect_nvidia", lambda: {
"gpu_name": "NVIDIA GB10",
"gpu_vram_gb": 64.0,
"gpu_count": 1,
"gpus": [],
"gpu_groups": [],
"homogeneous": True,
"backend": "cuda",
})
system = hardware.detect_system(fresh=True)
assert system["backend"] == "cuda"
assert system["cpu_arch"] == "arm64"
def test_detect_system_keeps_32_bit_arm_on_conservative_cpu_backend(monkeypatch):
"""Plain arm/armv7 is not the same as the ARM64-class cpu_arm fallback."""
_stub_common_probe(monkeypatch, "armv7l")
monkeypatch.setattr(hardware, "_detect_nvidia", lambda: None)
system = hardware.detect_system(fresh=True)
assert system["cpu_arch"] == "arm"
assert system["backend"] == "cpu_x86"
+25
View File
@@ -47,6 +47,12 @@ ARM64_SYSTEM = {
"gpu_vram_gb": 0,
}
ARM32_SYSTEM = {
"backend": "arm",
"gpu_name": None,
"gpu_vram_gb": 0,
}
AARCH64_SYSTEM = {
"backend": "aarch64",
"gpu_name": None,
@@ -79,6 +85,16 @@ def test_cpu_only_on_metal_apple_silicon_uses_cpu_arm_fallback():
assert metal_tps > 0
def test_cpu_only_on_gpu_backend_uses_detected_arm64_cpu_arch():
"""A GPU backend on an ARM64 host should use the ARM CPU fallback for cpu_only."""
cuda_arm64 = dict(CUDA_SYSTEM, cpu_arch="aarch64", cpu_name="Ampere Altra")
cuda_arm64_tps = _estimate_speed(DENSE_MODEL, QUANT, "cpu_only", cuda_arm64)
arm_tps = _estimate_speed(DENSE_MODEL, QUANT, "cpu_only", CPU_ARM_SYSTEM)
assert cuda_arm64_tps == pytest.approx(arm_tps, rel=1e-9, abs=1e-9)
assert cuda_arm64_tps > 0
@pytest.mark.parametrize(
"arm_alias_system",
[ARM64_SYSTEM, AARCH64_SYSTEM, CPU_ARM_SYSTEM],
@@ -93,6 +109,15 @@ def test_cpu_only_preserves_arm_backends(arm_alias_system):
assert alias_tps > 0
def test_cpu_only_does_not_treat_plain_arm_as_arm64_fallback():
"""Docker/OCI plain arm is not the ARM64-class fallback used for Apple Silicon."""
arm32_tps = _estimate_speed(DENSE_MODEL, QUANT, "cpu_only", ARM32_SYSTEM)
x86_tps = _estimate_speed(DENSE_MODEL, QUANT, "cpu_only", CPU_X86_SYSTEM)
assert arm32_tps == pytest.approx(x86_tps, rel=1e-9, abs=1e-9)
assert arm32_tps > 0
def test_cpu_only_preserves_known_cpu_backends():
"""Known CPU backends should be preserved, not rewritten to cpu_x86."""
for system in (CPU_X86_SYSTEM, CPU_ARM_SYSTEM):
+9
View File
@@ -165,6 +165,15 @@ def test_intel_mac_skipped(monkeypatch):
assert hardware._detect_apple_silicon() is None
def test_plain_arm_mac_skipped(monkeypatch):
"""Only ARM64-class Macs should enter the Apple Silicon Metal path."""
monkeypatch.setattr(hardware, "_remote_host", None)
monkeypatch.setattr(hardware.platform, "system", lambda: "Darwin")
monkeypatch.setattr(hardware.platform, "machine", lambda: "armv7l")
monkeypatch.setattr(hardware, "_run", _fake_sysctl())
assert hardware._detect_apple_silicon() is None
def test_detect_system_propagates_unified_memory(monkeypatch):
"""The unified_memory flag set by GPU detection must survive into the
system dict so the API and UI can report it (it was being dropped)."""