mirror of
https://github.com/open-jarvis/OpenJarvis.git
synced 2026-07-28 14:07:55 +00:00
205 lines
6.6 KiB
Python
205 lines
6.6 KiB
Python
"""AMD-specific hardware tests."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import patch
|
|
|
|
import pytest
|
|
|
|
from openjarvis.core.config import (
|
|
GpuInfo,
|
|
HardwareInfo,
|
|
_detect_amd_gpu,
|
|
recommend_engine,
|
|
)
|
|
|
|
pytestmark = pytest.mark.amd
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Detection / rocm-smi parsing
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestAMDDetection:
|
|
"""Tests for _detect_amd_gpu() against various rocm-smi outputs."""
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch(
|
|
"openjarvis.core.config._run_cmd",
|
|
side_effect=[
|
|
"AMD Instinct MI300X", # --showproductname
|
|
"GPU[0] : vram Total Memory (B): 206158430208", # --showmeminfo vram
|
|
"GPU[0] : Some info", # --showallinfo
|
|
],
|
|
)
|
|
def test_rocm_smi_parsing(self, mock_run, mock_which):
|
|
gpu = _detect_amd_gpu()
|
|
assert gpu is not None
|
|
assert gpu.vendor == "amd"
|
|
assert "MI300X" in gpu.name
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value=None)
|
|
def test_rocm_smi_not_found(self, mock_which):
|
|
assert _detect_amd_gpu() is None
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch(
|
|
"openjarvis.core.config._run_cmd",
|
|
side_effect=[
|
|
"AMD Instinct MI250X\nAMD Instinct MI250X", # --showproductname
|
|
"", # --showmeminfo vram (empty)
|
|
"", # --showallinfo (empty)
|
|
],
|
|
)
|
|
def test_amd_gpu_model(self, mock_run, mock_which):
|
|
"""First line of rocm-smi output is used as the GPU name."""
|
|
gpu = _detect_amd_gpu()
|
|
assert gpu is not None
|
|
assert "MI250X" in gpu.name
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch("openjarvis.core.config._run_cmd", side_effect=["", "", ""])
|
|
def test_rocm_smi_empty_output(self, mock_run, mock_which):
|
|
"""Empty output from rocm-smi --showproductname returns None."""
|
|
assert _detect_amd_gpu() is None
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch(
|
|
"openjarvis.core.config._run_cmd",
|
|
side_effect=[
|
|
"AMD Instinct MI300X",
|
|
"GPU[0] : vram Total Memory (B): 206158430208",
|
|
"GPU[0] : Some info",
|
|
],
|
|
)
|
|
def test_amd_vram_parsing(self, mock_run, mock_which):
|
|
"""VRAM is parsed from --showmeminfo vram output."""
|
|
gpu = _detect_amd_gpu()
|
|
assert gpu is not None
|
|
# 206158430208 bytes = ~192.0 GB
|
|
assert gpu.vram_gb == 192.0
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch(
|
|
"openjarvis.core.config._run_cmd",
|
|
side_effect=[
|
|
"AMD Instinct MI300X",
|
|
(
|
|
"GPU[0] : vram Total Memory (B): 206158430208\n"
|
|
"GPU[0] : vram Total Used Memory (B): 0\n"
|
|
"GPU[1] : vram Total Memory (B): 206158430208\n"
|
|
"GPU[1] : vram Total Used Memory (B): 0\n"
|
|
"GPU[2] : vram Total Memory (B): 206158430208\n"
|
|
"GPU[2] : vram Total Used Memory (B): 0\n"
|
|
"GPU[3] : vram Total Memory (B): 206158430208\n"
|
|
"GPU[3] : vram Total Used Memory (B): 0"
|
|
),
|
|
(
|
|
"GPU[0] : Info line\n"
|
|
"GPU[1] : Info line\n"
|
|
"GPU[2] : Info line\n"
|
|
"GPU[3] : Info line"
|
|
),
|
|
],
|
|
)
|
|
def test_amd_multi_gpu_count(self, mock_run, mock_which):
|
|
"""Multiple GPU entries in --showallinfo are counted."""
|
|
gpu = _detect_amd_gpu()
|
|
assert gpu is not None
|
|
assert gpu.count == 4
|
|
|
|
@patch("openjarvis.core.config.shutil.which", return_value="/usr/bin/rocm-smi")
|
|
@patch(
|
|
"openjarvis.core.config._run_cmd",
|
|
side_effect=[
|
|
"AMD Instinct MI300X",
|
|
"garbled output with no valid memory info",
|
|
"GPU[0] : Some info",
|
|
],
|
|
)
|
|
def test_amd_vram_parse_failure(self, mock_run, mock_which):
|
|
"""Garbled VRAM output falls back to 0.0."""
|
|
gpu = _detect_amd_gpu()
|
|
assert gpu is not None
|
|
assert gpu.vram_gb == 0.0
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Engine recommendation
|
|
# ---------------------------------------------------------------------------
|
|
|
|
|
|
class TestAMDEngineRecommendation:
|
|
"""Tests that AMD datacenter cards map to vllm, consumer cards to lemonade."""
|
|
|
|
def test_mi300x_recommends_vllm(self):
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="AMD EPYC 9654",
|
|
cpu_count=96,
|
|
ram_gb=768.0,
|
|
gpu=GpuInfo(
|
|
vendor="amd",
|
|
name="AMD Instinct MI300X",
|
|
vram_gb=192.0,
|
|
count=1,
|
|
),
|
|
)
|
|
assert recommend_engine(hw) == "vllm"
|
|
|
|
def test_mi350_recommends_vllm(self):
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="AMD EPYC 9654",
|
|
cpu_count=96,
|
|
ram_gb=768.0,
|
|
gpu=GpuInfo(
|
|
vendor="amd",
|
|
name="AMD Instinct MI350X",
|
|
vram_gb=288.0,
|
|
count=1,
|
|
),
|
|
)
|
|
assert recommend_engine(hw) == "vllm"
|
|
|
|
def test_amd_consumer_recommends_lemonade(self):
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="AMD Ryzen 9 7950X",
|
|
cpu_count=32,
|
|
ram_gb=64.0,
|
|
gpu=GpuInfo(
|
|
vendor="amd",
|
|
name="AMD Radeon RX 7900 XTX",
|
|
vram_gb=24.0,
|
|
count=1,
|
|
),
|
|
)
|
|
assert recommend_engine(hw) == "lemonade"
|
|
|
|
def test_amd_generic_recommends_lemonade(self):
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="AMD EPYC",
|
|
cpu_count=64,
|
|
ram_gb=256.0,
|
|
gpu=GpuInfo(vendor="amd", name="AMD GPU", vram_gb=0.0, count=1),
|
|
)
|
|
assert recommend_engine(hw) == "lemonade"
|
|
|
|
def test_amd_multi_gpu_recommends_vllm(self):
|
|
hw = HardwareInfo(
|
|
platform="linux",
|
|
cpu_brand="AMD EPYC 9654",
|
|
cpu_count=128,
|
|
ram_gb=1024.0,
|
|
gpu=GpuInfo(
|
|
vendor="amd",
|
|
name="AMD Instinct MI300X",
|
|
vram_gb=192.0,
|
|
count=4,
|
|
),
|
|
)
|
|
assert recommend_engine(hw) == "vllm"
|