172 lines
5.7 KiB
Python
172 lines
5.7 KiB
Python
"""Tests for GPU simulator (--gpu flag) using dbgpu database."""
|
|
|
|
import pytest
|
|
|
|
from whichllm.constants import _GiB
|
|
from whichllm.hardware.gpu_simulator import (
|
|
create_synthetic_gpu,
|
|
create_synthetic_gpus,
|
|
parse_synthetic_gpu_specs,
|
|
)
|
|
|
|
|
|
class TestMultiGPUSpecParsing:
|
|
def test_comma_separated_gpu_specs(self):
|
|
assert parse_synthetic_gpu_specs(["RTX 4090, RTX 3090"]) == [
|
|
"RTX 4090",
|
|
"RTX 3090",
|
|
]
|
|
|
|
def test_repeated_gpu_specs(self):
|
|
assert parse_synthetic_gpu_specs(["RTX 4090", "RTX 3090"]) == [
|
|
"RTX 4090",
|
|
"RTX 3090",
|
|
]
|
|
|
|
def test_count_shorthand(self):
|
|
assert parse_synthetic_gpu_specs(["2x RTX 4090, 1x RTX 3090"]) == [
|
|
"RTX 4090",
|
|
"RTX 4090",
|
|
"RTX 3090",
|
|
]
|
|
|
|
def test_empty_entry_raises(self):
|
|
with pytest.raises(ValueError, match="Empty GPU entry"):
|
|
parse_synthetic_gpu_specs(["RTX 4090,"])
|
|
|
|
def test_create_synthetic_gpus_expands_count(self):
|
|
gpus = create_synthetic_gpus(["2x RTX 4090"])
|
|
assert len(gpus) == 2
|
|
assert all(gpu.vendor == "nvidia" for gpu in gpus)
|
|
assert all(gpu.vram_bytes == 24 * _GiB for gpu in gpus)
|
|
|
|
def test_multi_gpu_vram_override_is_rejected(self):
|
|
with pytest.raises(ValueError, match="exactly one simulated GPU"):
|
|
create_synthetic_gpus(["2x RTX 4090"], vram_override_gb=24)
|
|
|
|
|
|
class TestKnownGPULookup:
|
|
def test_nvidia_rtx_4090(self):
|
|
gpu = create_synthetic_gpu("RTX 4090")
|
|
assert gpu.vram_bytes == 24 * _GiB
|
|
assert gpu.vendor == "nvidia"
|
|
assert gpu.memory_bandwidth_gbps is not None
|
|
assert gpu.compute_capability is not None
|
|
assert gpu.compute_capability[0] >= 8
|
|
assert "(simulated)" in gpu.name
|
|
|
|
def test_nvidia_rtx_3060(self):
|
|
gpu = create_synthetic_gpu("RTX 3060")
|
|
assert "RTX 3060" in gpu.name
|
|
assert "Ti" not in gpu.name # Should NOT match RTX 3060 Ti
|
|
assert gpu.vendor == "nvidia"
|
|
assert gpu.compute_capability is not None
|
|
|
|
def test_nvidia_rtx_3060_ti(self):
|
|
gpu = create_synthetic_gpu("RTX 3060 Ti")
|
|
assert "RTX 3060 Ti" in gpu.name
|
|
assert gpu.vram_bytes == 8 * _GiB
|
|
assert gpu.vendor == "nvidia"
|
|
|
|
def test_amd_rx_7900_xtx(self):
|
|
gpu = create_synthetic_gpu("RX 7900 XTX")
|
|
assert gpu.vram_bytes == 24 * _GiB
|
|
assert gpu.vendor == "amd"
|
|
assert gpu.memory_bandwidth_gbps is not None
|
|
|
|
def test_amd_strix_halo_with_vram_override(self):
|
|
gpu = create_synthetic_gpu("Radeon 8060S", vram_override_gb=96)
|
|
assert gpu.vram_bytes == 96 * _GiB
|
|
assert gpu.vendor == "amd"
|
|
assert gpu.shared_memory is True
|
|
assert gpu.memory_bandwidth_gbps == 256.0
|
|
|
|
def test_nvidia_gtx_1080(self):
|
|
gpu = create_synthetic_gpu("GTX 1080")
|
|
assert gpu.vram_bytes == 8 * _GiB
|
|
assert gpu.vendor == "nvidia"
|
|
assert gpu.compute_capability == (6, 1)
|
|
|
|
def test_a100_80gb_alias(self):
|
|
gpu = create_synthetic_gpu("A100 80GB")
|
|
assert gpu.vram_bytes == 80 * _GiB
|
|
assert gpu.vendor == "nvidia"
|
|
assert "(simulated)" in gpu.name
|
|
|
|
def test_h100_80gb_alias(self):
|
|
gpu = create_synthetic_gpu("H100 80GB")
|
|
assert gpu.vram_bytes == 80 * _GiB
|
|
assert gpu.vendor == "nvidia"
|
|
assert "(simulated)" in gpu.name
|
|
|
|
def test_intel_arc_pro_b70_curated_spec(self):
|
|
gpu = create_synthetic_gpu("Arc Pro B70")
|
|
assert gpu.name == "Intel Arc Pro B70 (simulated)"
|
|
assert gpu.vram_bytes == 32 * _GiB
|
|
assert gpu.vendor == "intel"
|
|
assert gpu.memory_bandwidth_gbps == 608.0
|
|
assert gpu.shared_memory is False
|
|
|
|
|
|
class TestAppleSiliconAliases:
|
|
@pytest.mark.parametrize(
|
|
"chip",
|
|
[
|
|
"M1",
|
|
"M1 Max",
|
|
"M1 Ultra",
|
|
"M2",
|
|
"M2 Max",
|
|
"M2 Ultra",
|
|
"M3",
|
|
"M3 Max",
|
|
"M3 Ultra",
|
|
"M4",
|
|
"M4 Max",
|
|
"M4 Ultra",
|
|
],
|
|
)
|
|
def test_apple_prefixed_alias_matches_plain_chip_name(self, chip):
|
|
plain = create_synthetic_gpu(chip)
|
|
prefixed = create_synthetic_gpu(f"Apple {chip}")
|
|
|
|
assert prefixed.name == plain.name
|
|
assert prefixed.vendor == "apple"
|
|
assert prefixed.vram_bytes == plain.vram_bytes
|
|
assert prefixed.memory_bandwidth_gbps == plain.memory_bandwidth_gbps
|
|
|
|
@pytest.mark.parametrize("chip", ["M1", "M2 Max", "M3 Ultra", "M4 Pro"])
|
|
def test_apple_silicon_has_shared_memory(self, chip):
|
|
gpu = create_synthetic_gpu(chip)
|
|
assert gpu.shared_memory is True
|
|
|
|
|
|
class TestVRAMOverride:
|
|
def test_override_known_gpu(self):
|
|
gpu = create_synthetic_gpu("RTX 4060 Ti", vram_override_gb=16)
|
|
assert gpu.vram_bytes == 16 * _GiB
|
|
assert gpu.memory_bandwidth_gbps is not None
|
|
|
|
def test_override_unknown_gpu(self):
|
|
gpu = create_synthetic_gpu("Nonexistent GPU 9999", vram_override_gb=48)
|
|
assert gpu.vram_bytes == 48 * _GiB
|
|
assert "(simulated)" in gpu.name
|
|
|
|
|
|
class TestUnknownGPU:
|
|
def test_unknown_without_vram_raises(self):
|
|
with pytest.raises(ValueError, match="Unknown GPU"):
|
|
create_synthetic_gpu("Nonexistent GPU 9999")
|
|
|
|
def test_unknown_with_vram_succeeds(self):
|
|
gpu = create_synthetic_gpu("Nonexistent GPU 9999", vram_override_gb=24)
|
|
assert gpu.vram_bytes == 24 * _GiB
|
|
|
|
|
|
class TestFuzzySearch:
|
|
def test_partial_name(self):
|
|
"""dbgpu fuzzy search should find GPU from partial name."""
|
|
gpu = create_synthetic_gpu("GTX 1080")
|
|
assert "1080" in gpu.name
|
|
assert gpu.vendor == "nvidia"
|