diff --git a/frigate/test/test_gpu_stats.py b/frigate/test/test_gpu_stats.py index 63ee27e65..a67537262 100644 --- a/frigate/test/test_gpu_stats.py +++ b/frigate/test/test_gpu_stats.py @@ -1,13 +1,14 @@ import unittest from unittest.mock import MagicMock, patch -from frigate.util import get_amd_gpu_stats, get_nvidia_gpu_stats +from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats, get_nvidia_gpu_stats class TestGpuStats(unittest.TestCase): def setUp(self): - self.nvidia_results = "name, utilization.gpu [%], memory.used [MiB], memory.total [MiB]\nNVIDIA GeForce RTX 3050, 42 %, 5036 MiB, 8192 MiB\n" self.amd_results = "Unknown Radeon card. <= R500 won't work, new cards might.\nDumping to -, line limit 1.\n1664070990.607556: bus 10, gpu 4.17%, ee 0.00%, vgt 0.00%, ta 0.00%, tc 0.00%, sx 0.00%, sh 0.00%, spi 0.83%, smx 0.00%, cr 0.00%, sc 0.00%, pa 0.00%, db 0.00%, cb 0.00%, vram 60.37% 294.04mb, gtt 0.33% 52.21mb, mclk 100.00% 1.800ghz, sclk 26.65% 0.533ghz\n" + self.intel_results = '''{"period":{"duration":1.194033,"unit":"ms"},"frequency":{"requested":0.000000,"actual":0.000000,"unit":"MHz"},"interrupts":{"count":3349.991164,"unit":"irq/s"},"rc6":{"value":47.844741,"unit":"%"},"engines":{"Render/3D/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"Blitter/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"Video/0":{"busy":4.533124,"sema":0.000000,"wait":0.000000,"unit":"%"},"Video/1":{"busy":6.194385,"sema":0.000000,"wait":0.000000,"unit":"%"},"VideoEnhance/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"}}},{"period":{"duration":1.189291,"unit":"ms"},"frequency":{"requested":0.000000,"actual":0.000000,"unit":"MHz"},"interrupts":{"count":0.000000,"unit":"irq/s"},"rc6":{"value":100.000000,"unit":"%"},"engines":{"Render/3D/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"Blitter/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"Video/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"Video/1":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"},"VideoEnhance/0":{"busy":0.000000,"sema":0.000000,"wait":0.000000,"unit":"%"}}}''' + self.nvidia_results = "name, utilization.gpu [%], memory.used [MiB], memory.total [MiB]\nNVIDIA GeForce RTX 3050, 42 %, 5036 MiB, 8192 MiB\n" @patch("subprocess.run") def test_amd_gpu_stats(self, sp): @@ -19,7 +20,7 @@ class TestGpuStats(unittest.TestCase): assert amd_stats == {"gpu_usage": "4.17 %", "memory_usage": "60.37 %"} @patch("subprocess.run") - def test_amd_gpu_stats(self, sp): + def test_nvidia_gpu_stats(self, sp): process = MagicMock() process.returncode = 0 process.stdout = self.nvidia_results @@ -30,3 +31,15 @@ class TestGpuStats(unittest.TestCase): "gpu_usage": "42 %", "memory_usage": "61.5 %", } + + @patch("subprocess.run") + def test_intel_gpu_stats(self, sp): + process = MagicMock() + process.returncode = 0 + process.stdout = self.intel_results + sp.return_value = process + intel_stats = get_intel_gpu_stats() + assert intel_stats == { + "gpu_usage": "10.73 %", + "memory_usage": "- %", + } diff --git a/frigate/util.py b/frigate/util.py index a916c1040..ad8d0faa4 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -811,10 +811,10 @@ def get_amd_gpu_stats() -> dict[str, str]: def get_intel_gpu_stats() -> dict[str, str]: """Get stats using intel_gpu_top.""" - radeontop_command = ["timeout", "1s", "intel_gpu_top", "-J", "-o", "-", "-s", "1"] + intel_gpu_top_command = ["timeout", "0.1s", "intel_gpu_top", "-J", "-o", "-", "-s", "1"] p = sp.run( - radeontop_command, + intel_gpu_top_command, encoding="ascii", capture_output=True, ) @@ -823,15 +823,24 @@ def get_intel_gpu_stats() -> dict[str, str]: logger.error(p.stderr) return None else: - usages = p.stdout.split(",") + readings = json.loads(f'[{p.stdout}]') results: dict[str, str] = {} - for hw in usages: - if "gpu" in hw: - results["gpu_usage"] = f"{hw.strip().split(' ')[1].split(' ')[0]} %" - elif "vram" in hw: - results["memory_usage"] = f"{hw.strip().split(' ')[1].split(' ')[0]} %" + for reading in readings: + if reading.get("engines", {}).get("Video/0", {}).get( + "busy", 0 + ) or reading.get("engines", {}).get("Video/1", {}).get("busy", 0): + gpu_usage = round( + float(reading.get("engines", {}).get("Video/0", {}).get("busy", 0)) + + float( + reading.get("engines", {}).get("Video/1", {}).get("busy", 0) + ), + 2, + ) + results["gpu_usage"] = f"{gpu_usage} %" + break + results["memory_usage"] = "- %" return results