Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into fix/473-gpu-and-fps-f…
Browse files Browse the repository at this point in the history
…an-error
  • Loading branch information
mathoudebine committed Mar 10, 2024
2 parents 335a4d5 + 2a25630 commit eb54152
Show file tree
Hide file tree
Showing 9 changed files with 254 additions and 50 deletions.
5 changes: 5 additions & 0 deletions library/sensors/sensors.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,11 @@ def fps() -> int:
def fan_percent() -> float:
pass

@staticmethod
@abstractmethod
def frequency() -> float:
pass

@staticmethod
@abstractmethod
def is_available() -> bool:
Expand Down
23 changes: 22 additions & 1 deletion library/sensors/sensors_librehardwaremonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,34 @@ def fan_percent(cls) -> float:
try:
for sensor in gpu_to_use.Sensors:
if sensor.SensorType == Hardware.SensorType.Control:
return float(sensor.Value)
if sensor.Value:
return float(sensor.Value)
except:
pass

# No Fan Speed sensor for this GPU model
return math.nan

@classmethod
def frequency(cls) -> float:
gpu_to_use = cls.get_gpu_to_use()
if gpu_to_use is None:
# GPU not supported
return math.nan

try:
for sensor in gpu_to_use.Sensors:
if sensor.SensorType == Hardware.SensorType.Clock:
# Keep only real core clocks, ignore effective core clocks
if "Core" in str(sensor.Name) and "Effective" not in str(sensor.Name):
if sensor.Value:
return float(sensor.Value)
except:
pass

# No Frequency sensor for this GPU model
return math.nan

@classmethod
def is_available(cls) -> bool:
cls.gpu_name = get_gpu_name()
Expand Down
64 changes: 43 additions & 21 deletions library/sensors/sensors_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ def fan_percent() -> float:
else:
return math.nan

@staticmethod
def frequency() -> float:
global DETECTED_GPU
if DETECTED_GPU == GpuType.AMD:
return GpuAmd.frequency()
elif DETECTED_GPU == GpuType.NVIDIA:
return GpuNvidia.frequency()
else:
return math.nan

@staticmethod
def is_available() -> bool:
global DETECTED_GPU
Expand Down Expand Up @@ -257,13 +267,18 @@ def fan_percent() -> float:
if fans:
for name, entries in fans.items():
for entry in entries:
if "gpu" in (entry.label or name):
if "gpu" in (entry.label.lower() or name.lower()):
return entry.percent
except:
pass

return math.nan

@staticmethod
def frequency() -> float:
# Not supported by Python libraries
return math.nan

@staticmethod
def is_available() -> bool:
try:
Expand All @@ -277,52 +292,43 @@ class GpuAmd(sensors.Gpu):
def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
if pyamdgpuinfo:
# Unlike other sensors, AMD GPU with pyamdgpuinfo pulls in all the stats at once
i = 0
amd_gpus = []
while i < pyamdgpuinfo.detect_gpus():
amd_gpus.append(pyamdgpuinfo.get_gpu(i))
i = i + 1
pyamdgpuinfo.detect_gpus()
amd_gpu = pyamdgpuinfo.get_gpu(0)

try:
memory_used_all = [item.query_vram_usage() for item in amd_gpus]
memory_used_bytes = sum(memory_used_all) / len(memory_used_all)
memory_used_bytes = amd_gpu.query_vram_usage()
memory_used = memory_used_bytes / 1000000
except:
memory_used_bytes = math.nan
memory_used = math.nan

try:
memory_total_all = [item.memory_info["vram_size"] for item in amd_gpus]
memory_total_bytes = sum(memory_total_all) / len(memory_total_all)
memory_total_bytes = amd_gpu.memory_info["vram_size"]
memory_percentage = (memory_used_bytes / memory_total_bytes) * 100
except:
memory_percentage = math.nan

try:
load_all = [item.query_load() for item in amd_gpus]
load = (sum(load_all) / len(load_all)) * 100
load = amd_gpu.query_load()
except:
load = math.nan

try:
temperature_all = [item.query_temperature() for item in amd_gpus]
temperature = sum(temperature_all) / len(temperature_all)
temperature = amd_gpu.query_temperature()
except:
temperature = math.nan

return load, memory_percentage, memory_used, temperature
elif pyadl:
amd_gpus = pyadl.ADLManager.getInstance().getDevices()
amd_gpu = pyadl.ADLManager.getInstance().getDevices()[0]

try:
load_all = [item.getCurrentUsage() for item in amd_gpus]
load = (sum(load_all) / len(load_all))
load = amd_gpu.getCurrentUsage()
except:
load = math.nan

try:
temperature_all = [item.getCurrentTemperature() for item in amd_gpus]
temperature = sum(temperature_all) / len(temperature_all)
temperature = amd_gpu.getCurrentTemperature()
except:
temperature = math.nan

Expand All @@ -337,17 +343,33 @@ def fps() -> int:
@staticmethod
def fan_percent() -> float:
try:
# Try with psutil fans
fans = sensors_fans()
if fans:
for name, entries in fans.items():
for entry in entries:
if "gpu" in (entry.label or name):
return entry.current
if "gpu" in (entry.label.lower() or name.lower()):
return entry.percent

# Try with pyadl if psutil did not find GPU fan
if pyadl:
return pyadl.ADLManager.getInstance().getDevices()[0].getCurrentFanSpeed(
pyadl.ADL_DEVICE_FAN_SPEED_TYPE_PERCENTAGE)
except:
pass

return math.nan

@staticmethod
def frequency() -> float:
if pyamdgpuinfo:
pyamdgpuinfo.detect_gpus()
return pyamdgpuinfo.get_gpu(0).query_sclk() / 1000000
elif pyadl:
return pyadl.ADLManager.getInstance().getDevices()[0].getCurrentEngineClock()
else:
return math.nan

@staticmethod
def is_available() -> bool:
try:
Expand Down
4 changes: 4 additions & 0 deletions library/sensors/sensors_stub_random.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ def fps() -> int:
def fan_percent() -> float:
return random.uniform(0, 100)

@staticmethod
def frequency() -> float:
return random.uniform(800, 3400)

@staticmethod
def is_available() -> bool:
return True
Expand Down
5 changes: 5 additions & 0 deletions library/sensors/sensors_stub_static.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
GPU_MEM_TOTAL_SIZE_GB = 32
NETWORK_SPEED_BYTES = 1061000000
GPU_FPS = 120
GPU_FREQ_MHZ = 1500.0


class Cpu(sensors.Cpu):
Expand Down Expand Up @@ -73,6 +74,10 @@ def fps() -> int:
def fan_percent() -> float:
return PERCENTAGE_SENSOR_VALUE

@staticmethod
def frequency() -> float:
return GPU_FREQ_MHZ

@staticmethod
def is_available() -> bool:
return True
Expand Down
43 changes: 41 additions & 2 deletions library/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ class CPU:
last_values_cpu_percentage = []
last_values_cpu_temperature = []
last_values_cpu_fan_speed = []
last_values_cpu_frequency = []

@classmethod
def percentage(cls):
Expand All @@ -259,12 +260,26 @@ def percentage(cls):

@classmethod
def frequency(cls):
freq_ghz = sensors.Cpu.frequency() / 1000
theme_data = config.THEME_DATA['STATS']['CPU']['FREQUENCY']

save_last_value(freq_ghz, cls.last_values_cpu_frequency,
theme_data['LINE_GRAPH'].get("HISTORY_SIZE", DEFAULT_HISTORY_SIZE))

display_themed_value(
theme_data=config.THEME_DATA['STATS']['CPU']['FREQUENCY']['TEXT'],
value=f'{sensors.Cpu.frequency() / 1000:.2f}',
theme_data=theme_data['TEXT'],
value=f'{freq_ghz:.2f}',
unit=" GHz",
min_size=4
)
display_themed_progress_bar(theme_data['GRAPH'], freq_ghz)
display_themed_radial_bar(
theme_data=theme_data['RADIAL'],
value=f'{freq_ghz:.2f}',
unit=" GHz",
min_size=4
)
display_themed_line_graph(theme_data['LINE_GRAPH'], cls.last_values_cpu_frequency)

@classmethod
def load(cls):
Expand Down Expand Up @@ -344,12 +359,14 @@ class Gpu:
last_values_gpu_temperature = []
last_values_gpu_fps = []
last_values_gpu_fan_speed = []
last_values_gpu_frequency = []

@classmethod
def stats(cls):
load, memory_percentage, memory_used_mb, temperature = sensors.Gpu.stats()
fps = sensors.Gpu.fps()
fan_percent = sensors.Gpu.fan_percent()
freq_ghz = sensors.Gpu.frequency() / 1000

theme_gpu_data = config.THEME_DATA['STATS']['GPU']

Expand All @@ -363,6 +380,8 @@ def stats(cls):
theme_gpu_data['FPS']['LINE_GRAPH'].get("HISTORY_SIZE", DEFAULT_HISTORY_SIZE))
save_last_value(fan_percent, cls.last_values_gpu_fan_speed,
theme_gpu_data['FAN_SPEED']['LINE_GRAPH'].get("HISTORY_SIZE", DEFAULT_HISTORY_SIZE))
save_last_value(freq_ghz, cls.last_values_gpu_frequency,
theme_gpu_data['FREQUENCY']['LINE_GRAPH'].get("HISTORY_SIZE", DEFAULT_HISTORY_SIZE))

################################ for backward compatibility only
gpu_mem_graph_data = theme_gpu_data['MEMORY']['GRAPH']
Expand Down Expand Up @@ -520,6 +539,26 @@ def stats(cls):
display_themed_percent_radial_bar(gpu_fan_radial_data, fan_percent)
display_themed_line_graph(gpu_fan_line_graph_data, cls.last_values_gpu_fan_speed)

# GPU Frequency (Ghz)
gpu_freq_text_data = theme_gpu_data['FREQUENCY']['TEXT']
gpu_freq_radial_data = theme_gpu_data['FREQUENCY']['RADIAL']
gpu_freq_graph_data = theme_gpu_data['FREQUENCY']['GRAPH']
gpu_freq_line_graph_data = theme_gpu_data['FREQUENCY']['LINE_GRAPH']
display_themed_value(
theme_data=gpu_freq_text_data,
value=f'{freq_ghz:.2f}',
unit=" GHz",
min_size=4
)
display_themed_progress_bar(gpu_freq_graph_data, freq_ghz)
display_themed_radial_bar(
theme_data=gpu_freq_radial_data,
value=f'{freq_ghz:.2f}',
unit=" GHz",
min_size=4
)
display_themed_line_graph(gpu_freq_line_graph_data, cls.last_values_gpu_frequency)

@staticmethod
def is_available():
return sensors.Gpu.is_available()
Expand Down
1 change: 1 addition & 0 deletions res/themes/Cyberdeck/theme.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ STATS:
FPS:
TEXT:
SHOW: True
SHOW_UNIT: False
X: 46
Y: 279
MIN_SIZE: 4
Expand Down
Loading

0 comments on commit eb54152

Please sign in to comment.