~kris/dots

srice

ref: e9b48d06a8541f3eda5c4db90382ab3c77183afb srice/.config/conky/lean-conky/lib/components/gpu_nvml -rwxr-xr-x 4.0 KiB
e9b48d06 — Kris Yotam xprofile: systemd-aware pipewire start + blueman-applet; sb-internet: tolerate missing /proc/net/wireless 2 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#!/usr/bin/env python
# vim: ft=python:ts=4:sw=4:et:ai:cin

# NVML driver for the gpu.nvidia component
import pynvml
from contextlib import contextmanager
import subprocess
import os.path as osp


@contextmanager
def nvml(flags=0):
    pynvml.nvmlInitWithFlags(flags)
    yield
    pynvml.nvmlShutdown()


def process_name(pid, full=False):
    try:
        proc = subprocess.run(
            ["ps", "-o", "cmd=", str(pid)],
            capture_output=True,
            encoding="utf-8",
            shell=False,
        )
        if proc.returncode > 0:
            raise SystemError()
        cmdline = proc.stdout
        return (
            cmdline if full else osp.basename(cmdline.split(" ", maxsplit=1)[0])
        ).strip()
    except:
        return "[unknown]"


with nvml():

    def query(f, *args, default=None, **kw):
        try:
            f = getattr(pynvml, f)
            val = f(*args, **kw)
        except:
            val = default
        if isinstance(val, bytes):
            val = val.decode("utf-8")
        return val

    def query_and_print(name, f, *args, default=None, **kw):
        val = query(f, *args, default=default, **kw)
        print_entry(name, val)
        return val

    def print_entry(k, v):
        print(f"{v!r}," if k is None else f"{k}={v!r},")

    gpu_count = query("nvmlDeviceGetCount")

    print("{")
    for gi in range(gpu_count):
        print("{")
        handle = query("nvmlDeviceGetHandleByIndex", gi)

        def q(f, *args, **kw):
            return query(f, handle, *args, **kw)

        def qp(name, f, *args, **kw):
            return query_and_print(name, f, handle, *args, **kw)

        qp("model_name", "nvmlDeviceGetName")

        memory_info = q("nvmlDeviceGetMemoryInfo")
        print_entry("mem_used", memory_info.used)
        print_entry("mem_total", memory_info.total)
        print_entry("mem_free", memory_info.free)

        util_rates = q("nvmlDeviceGetUtilizationRates")
        print_entry("gpu_util", util_rates.gpu)
        print_entry("mem_util", util_rates.memory)

        qp("fan_speed", "nvmlDeviceGetFanSpeed")
        qp("gpu_temp", "nvmlDeviceGetTemperature", pynvml.NVML_TEMPERATURE_GPU)
        qp(
            "gpu_temp_thres",
            "nvmlDeviceGetTemperatureThreshold",
            pynvml.NVML_TEMPERATURE_THRESHOLD_GPU_MAX,
            default=100,
        )
        print_entry("power_usage", q("nvmlDeviceGetPowerUsage") / 1000.0)
        print_entry("power_limit", q("nvmlDeviceGetPowerManagementLimit") / 1000.0)

        processes = {}
        for proc_type, proc_query in (
            ("c", "nvmlDeviceGetComputeRunningProcesses"),
            ("g", "nvmlDeviceGetGraphicsRunningProcesses"),
        ):
            for proc in q(proc_query):
                pid = proc.pid

                processes[pid] = dict(
                    pid=pid,
                    name=process_name(pid),
                    type=proc_type,
                    gpu_util=0,
                    mem_util=0,
                    gpu_mem=proc.usedGpuMemory,
                    gpu_instance=proc.gpuInstanceId,
                )

        if len(processes) > 0:
            timestamp = 0  # list all processes
            samples = q("nvmlDeviceGetProcessUtilization", timestamp)
            for s in samples:
                if s.pid in processes:
                    processes[s.pid].update(
                        dict(
                            gpu_util=s.smUtil,
                            mem_util=s.memUtil,
                        )
                    )

        processes = list(processes.values())
        processes.sort(key=lambda x: x["gpu_util"], reverse=True)
        print("processes={")
        for p in processes:
            print("{")
            for k in (
                "pid",
                "name",
                "type",
                "gpu_util",
                "mem_util",
                "gpu_mem",
                "gpu_instance",
            ):
                print_entry(k, p[k])
            print("},")
        print("}")
        print("},")
    print("}")