~kris/dots

srice

ref: c776188f504eb2e42ec1d359bdfd97e513b02add srice/.config/conky/lean-conky/lib/components/gpu_nvml -rwxr-xr-x 4.0 KiB
c776188f — Kris Yotam add bm bookmark manager and dsnip launcher 5 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("}")