-
Notifications
You must be signed in to change notification settings - Fork 40
Expand file tree
/
Copy pathfree_gpus.py
More file actions
executable file
·103 lines (85 loc) · 2.78 KB
/
Copy pathfree_gpus.py
File metadata and controls
executable file
·103 lines (85 loc) · 2.78 KB
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
#!/usr/bin/env python
# Parse nvidia-smi for pids and kill all GPU users
# Tested on nvidia-smi 370.23
import os, re, sys, subprocess
import pwd
from collections import defaultdict
def tokenize(cmd):
if isinstance(cmd, list):
return cmd
if isinstance(cmd, bytes):
cmd = cmd.decode("ascii")
if isinstance(cmd, str):
cmd = cmd.split(None)
return cmd
def run_command(cmd):
"""Run command, return output as string."""
output = subprocess.Popen(cmd, stdout=subprocess.PIPE,
shell=True).communicate()[0]
return output.decode("ascii")
def run_shell(cmd):
"""Runs shell command, returns list of outputted lines
with newlines stripped."""
cmd = tokenize(cmd)
p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
(stdout, stderr) = p.communicate()
stdout = stdout.decode("ascii") # turn into string to make Python3 happy
lines = stdout.split('\n')
stripped_lines = []
for l in lines:
stripped_line = l.strip()
if l:
stripped_lines.append(stripped_line)
return stripped_lines
def run_shell_background(cmd_orig):
"""Runs shell command in background, returns pid."""
cmd = tokenize(cmd_orig)
p = subprocess.Popen(cmd, close_fds=True)
print("[%d] %s " % (p.pid, cmd_orig))
def get_pid_gpu_map():
"""Returns map of GPU id to memory allocated on that GPU."""
output = run_command("nvidia-smi")
gpu_output = output[output.find("GPU Memory"):]
# lines of the form
# | 0 8734 C python 11705MiB |
regex = re.compile(r"[|]\s+?(?P<gpu_id>\d+)\D+?(?P<pid>\d+).+[ ]"
"(?P<gpu_memory>\d+)MiB")
rows = gpu_output.split("\n")
pids = []
pid_gpu_map = defaultdict(list)
for row in gpu_output.split("\n"):
m = regex.search(row)
if not m:
continue
pid = int(m.group("pid"))
gpu_id = int(m.group("gpu_id"))
print("pid %s using gpu %s"%(pid, gpu_id))
pid_gpu_map[pid].append(gpu_id)
return pid_gpu_map
def kill_pids(pids_to_kill):
pids = []
for pid_to_kill in pids_to_kill:
pid = run_shell_background("sudo kill -9 "+str(pid_to_kill))
pids.append(pid)
return pids
def owner(pid):
'''Return username of UID of process pid'''
UID = 1
EUID = 2
for ln in open('/proc/%d/status' % pid):
if ln.startswith('Uid:'):
uid = int(ln.split()[UID])
return pwd.getpwuid(uid).pw_name
if __name__ == '__main__':
pid_gpu_map = get_pid_gpu_map()
print("%10s %10s %s" %("pid", "username", "gpu"))
for pid in pid_gpu_map:
print("%10s %10s %s" %(pid, owner(pid), pid_gpu_map[pid]))
answer = input("kill these? (Y/n) ")
if not answer:
answer = "y"
if answer.lower() == "y":
pids = kill_pids(pid_gpu_map.keys())
else:
print("Didn't get y, doing nothing")