Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2685e20782 | |||
| e06555d14f | |||
| 27604247af | |||
| 1f9984893b | |||
| 37a1cfe942 | |||
| 8ae743e166 | |||
| 5f57991308 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,6 +3,8 @@
|
|||||||
__pycache__/
|
__pycache__/
|
||||||
*.py[cod]
|
*.py[cod]
|
||||||
*$py.class
|
*$py.class
|
||||||
|
try.py
|
||||||
|
.vscode/
|
||||||
|
|
||||||
# C extensions
|
# C extensions
|
||||||
*.so
|
*.so
|
||||||
|
|||||||
44
README.md
44
README.md
@@ -6,7 +6,7 @@ A naive tool for observing gpu status and auto set visible gpu in python code.
|
|||||||
|
|
||||||
1. install the package.
|
1. install the package.
|
||||||
```shell
|
```shell
|
||||||
pip install https://git.zmy.pub/zmyme/gpuutil/archive/v0.0.2.tar.gz
|
pip install https://git.zmy.pub/zmyme/gpuutil/archive/v0.0.3.tar.gz
|
||||||
```
|
```
|
||||||
|
|
||||||
2. for observing gpu status, just input
|
2. for observing gpu status, just input
|
||||||
@@ -15,29 +15,45 @@ python -m gpuutil <options>
|
|||||||
```
|
```
|
||||||
when directly running ```python -m gpuutil```, you would probably get:
|
when directly running ```python -m gpuutil```, you would probably get:
|
||||||
```text
|
```text
|
||||||
+---+------+------+---------+---------+------+---------------+
|
+----+------+------+----------+----------+------+----------------+
|
||||||
|ID | Fan | Temp | Pwr | Freq | Util | Vmem |
|
| ID | Fan | Temp | Pwr | Freq | Util | Vmem |
|
||||||
+---+------+------+---------+---------+------+---------------+
|
+----+------+------+----------+----------+------+----------------+
|
||||||
| 0 | 22 % | 33 C | 4.47 W | 300 MHz | 0 % | 1569/11019 MiB|
|
| 0 | 22 % | 21 C | 9.11 W | 300 MHz | 0 % | 3089/11019 MiB |
|
||||||
| 1 | 22 % | 35 C | 3.87 W | 300 MHz | 0 % | 3/11019 MiB|
|
| 1 | 22 % | 23 C | 6.28 W | 300 MHz | 0 % | 786/11019 MiB |
|
||||||
| 2 | 22 % | 36 C | 8.22 W | 300 MHz | 0 % | 3/11019 MiB|
|
| 2 | 38 % | 59 C | 92.04 W | 1890 MHz | 6 % | 3608/11019 MiB |
|
||||||
| 3 | 22 % | 36 C | 21.82 W | 300 MHz | 0 % | 3/11019 MiB|
|
| 3 | 40 % | 67 C | 246.38 W | 1740 MHz | 93 % | 3598/11019 MiB |
|
||||||
+---+------+------+---------+---------+------+---------------+
|
+----+------+------+----------+----------+------+----------------+
|
||||||
[34860|0] user1(783 MiB) python train.py --some -args
|
| Process Info |
|
||||||
[38694|0] user2(783 MiB) python train.py --some --other -args
|
+----------------------------------------------------------------+
|
||||||
|
| [26107|0] user1(737 MiB) python |
|
||||||
|
| [34033|0,1] user2(1566 MiB) python |
|
||||||
|
| [37190|0] user2(783 MiB) python |
|
||||||
|
| [37260|0] user2(783 MiB) python |
|
||||||
|
| [30356|2] user3(3605 MiB) python train.py --args --some really |
|
||||||
|
| long arguments |
|
||||||
|
| [34922|3] user3(3595 MiB) python train.py --args --some really |
|
||||||
|
| long arguments version 2 |
|
||||||
|
+----------------------------------------------------------------+
|
||||||
```
|
```
|
||||||
To get more information, run ```python -m gpuutil -h```, you would get:
|
To get more information, run ```python -m gpuutil -h```, you would get:
|
||||||
```text
|
```text
|
||||||
python __main__.py -h
|
usage: __main__.py [-h] [--profile PROFILE] [--cols COLS] [--style STYLE]
|
||||||
usage: __main__.py [-h] [--profile PROFILE] [--cols COLS] [--show-process SHOW_PROCESS] [--save]
|
[--show-process SHOW_PROCESS] [--vertical VERTICAL] [--save]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-h, --help show this help message and exit
|
-h, --help show this help message and exit
|
||||||
--profile PROFILE, -p PROFILE
|
--profile PROFILE, -p PROFILE
|
||||||
profile keyword, corresponding configuration are saved in ~/.gpuutil.conf
|
profile keyword, corresponding configuration are saved in ~/.gpuutil.conf
|
||||||
--cols COLS, -c COLS colums to show
|
--cols COLS, -c COLS colums to show.(Availabel cols: ['ID', 'Fan', 'Temp', 'TempMax', 'Pwr',
|
||||||
|
'PwrMax', 'Freq', 'FreqMax', 'Util', 'Vmem', 'UsedMem', 'TotalMem', 'FreeMem',
|
||||||
|
'Users']
|
||||||
|
--style STYLE, -sty STYLE
|
||||||
|
column style, format: |c|l:15|r|c:14rl:13|, c,l,r are align methods, | is line
|
||||||
|
and :(int) are width limit.
|
||||||
--show-process SHOW_PROCESS, -sp SHOW_PROCESS
|
--show-process SHOW_PROCESS, -sp SHOW_PROCESS
|
||||||
whether show process or not
|
whether show process or not
|
||||||
|
--vertical VERTICAL, -v VERTICAL
|
||||||
|
whether show each user in different lines. (show user vertically)
|
||||||
--save save config to profile
|
--save save config to profile
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,34 @@ def save_config(config):
|
|||||||
with open(configdir, 'w+', encoding='utf-8') as f:
|
with open(configdir, 'w+', encoding='utf-8') as f:
|
||||||
json.dump(config, f, ensure_ascii=False, indent=4)
|
json.dump(config, f, ensure_ascii=False, indent=4)
|
||||||
|
|
||||||
|
# style format: |c|l:15|r|c:14rl:13|
|
||||||
|
def parse_style(style):
|
||||||
|
if style is None:
|
||||||
|
return None, None
|
||||||
|
components = []
|
||||||
|
limits = []
|
||||||
|
while len(style) > 0:
|
||||||
|
ch = style[0]
|
||||||
|
if ch == '|':
|
||||||
|
components.append(ch)
|
||||||
|
style = style[1:]
|
||||||
|
continue
|
||||||
|
elif ch in ['l', 'r', 'c']:
|
||||||
|
limit = None
|
||||||
|
style = style[1:]
|
||||||
|
if style[0] == ':':
|
||||||
|
style = style[1:]
|
||||||
|
digits = ''
|
||||||
|
while style[0].isdigit():
|
||||||
|
digits += style[0]
|
||||||
|
style = style[1:]
|
||||||
|
if digits != '':
|
||||||
|
limit = int(digits)
|
||||||
|
components.append(ch)
|
||||||
|
limits.append(limit)
|
||||||
|
style = ''.join(components)
|
||||||
|
return style, limits
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
stat = GPUStat()
|
stat = GPUStat()
|
||||||
|
|
||||||
@@ -34,12 +62,16 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
parser = argparse.ArgumentParser()
|
||||||
parser.add_argument('--profile', '-p', default=None, type=str, help='profile keyword, corresponding configuration are saved in ~/.gpuutil.conf')
|
parser.add_argument('--profile', '-p', default=None, type=str, help='profile keyword, corresponding configuration are saved in ~/.gpuutil.conf')
|
||||||
parser.add_argument('--cols', '-c', type=csv2list, help='colums to show')
|
parser.add_argument('--cols', '-c', type=csv2list, help='colums to show.(Availabel cols: {0}'.format(avaliable_cols))
|
||||||
|
parser.add_argument('--style', '-sty', type=str, default=None, help='column style, format: |c|l:15|r|c:14rl:13|, c,l,r are align methods, | is line and :(int) are width limit.')
|
||||||
parser.add_argument('--show-process', '-sp', default=True, type=str2bool, help='whether show process or not')
|
parser.add_argument('--show-process', '-sp', default=True, type=str2bool, help='whether show process or not')
|
||||||
|
parser.add_argument('--vertical', '-v', default=False, type=str2bool, help='whether show each user in different lines. (show user vertically)')
|
||||||
parser.add_argument('--save', default=False, action="store_true", help='save config to profile')
|
parser.add_argument('--save', default=False, action="store_true", help='save config to profile')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
cols = args.cols if args.cols is not None else recommended_cols
|
cols = args.cols if args.cols is not None else recommended_cols
|
||||||
show_process = args.show_process
|
show_process = args.show_process
|
||||||
|
style, limit = parse_style(args.style)
|
||||||
|
vertical = args.vertical
|
||||||
unexpected_cols = []
|
unexpected_cols = []
|
||||||
for col in cols:
|
for col in cols:
|
||||||
if col not in avaliable_cols:
|
if col not in avaliable_cols:
|
||||||
@@ -50,7 +82,10 @@ if __name__ == '__main__':
|
|||||||
if args.save:
|
if args.save:
|
||||||
params = {
|
params = {
|
||||||
"cols": cols,
|
"cols": cols,
|
||||||
"show-process": show_process
|
"style": style,
|
||||||
|
"limit": limit,
|
||||||
|
"show-process": show_process,
|
||||||
|
"vertical": vertical
|
||||||
}
|
}
|
||||||
profile = args.profile if args.profile is not None else input('Please input your profile name:\n>>> ')
|
profile = args.profile if args.profile is not None else input('Please input your profile name:\n>>> ')
|
||||||
config = load_config()
|
config = load_config()
|
||||||
@@ -62,6 +97,16 @@ if __name__ == '__main__':
|
|||||||
params = config[args.profile]
|
params = config[args.profile]
|
||||||
cols = params["cols"]
|
cols = params["cols"]
|
||||||
show_process = params["show-process"]
|
show_process = params["show-process"]
|
||||||
|
style = None
|
||||||
|
limit = None
|
||||||
|
vertical = False
|
||||||
|
if "style" in params:
|
||||||
|
style = params["style"]
|
||||||
|
if "limit" in params:
|
||||||
|
limit = params["limit"]
|
||||||
|
if "vertical" in params:
|
||||||
|
vertical = params["vertical"]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ValueError('Profile do not exist.\nAvaliable Profiles:{0}'.format(','.join(list(config.keys()))))
|
raise ValueError('Profile do not exist.\nAvaliable Profiles:{0}'.format(','.join(list(config.keys()))))
|
||||||
stat.show(enabled_cols = cols, show_command=show_process)
|
stat.show(enabled_cols = cols, colsty=style, colsz=limit, vertical=vertical, show_command=show_process)
|
||||||
@@ -168,50 +168,94 @@ def get_basic_process_info_windows():
|
|||||||
}
|
}
|
||||||
return processes
|
return processes
|
||||||
|
|
||||||
def draw_table(table, header_line = 0, c_align = 'r', h_align='c', delemeter = ' | ', joint_delemeter = '-+-'):
|
def draw_table(table, rowsty=None, colsty=None, colsz = None):
|
||||||
# calculate max lengths.
|
def justify(s, align, width):
|
||||||
num_columns = len(table[0])
|
if align == 'c':
|
||||||
def cvt_align(align, num_columns):
|
s = s.center(width)
|
||||||
if type(align) is str:
|
elif align == 'r':
|
||||||
if len(align) == 1:
|
s = s.rjust(width)
|
||||||
return [align] * num_columns
|
elif align == 'l':
|
||||||
elif len(align) == num_columns:
|
s = s.ljust(width)
|
||||||
return list(align)
|
return s
|
||||||
else:
|
|
||||||
raise ValueError('align flag length mismatch')
|
num_cols = len(table[0])
|
||||||
else:
|
if rowsty is None:
|
||||||
return align
|
rowsty = '|' + '|'.join(['c']*len(table)) + '|'
|
||||||
c_align = cvt_align(c_align, num_columns)
|
if colsty is None:
|
||||||
h_align = cvt_align(h_align, num_columns)
|
colsty = '|' + '|'.join(['c']*num_cols) + '|'
|
||||||
max_lengths = [0] * num_columns
|
# check tables.
|
||||||
|
for row in table:
|
||||||
|
if len(row) != num_cols:
|
||||||
|
raise ValueError('different cols!')
|
||||||
|
col_width = [0] * num_cols
|
||||||
|
if colsz is None:
|
||||||
|
colsz = [None] * num_cols
|
||||||
|
|
||||||
|
# collect widths.
|
||||||
for row in table:
|
for row in table:
|
||||||
for i, col in enumerate(row):
|
for i, col in enumerate(row):
|
||||||
if len(col) > max_lengths[i]:
|
col = str(col)
|
||||||
max_lengths[i] = len(col)
|
width = max([len(c) for c in col.split('\n')])
|
||||||
width = sum(max_lengths) + num_columns * len(delemeter) + 1
|
if colsz[i] is not None and colsz[i] < width:
|
||||||
hline = '+'
|
width = colsz[i]
|
||||||
hline += joint_delemeter.join(['-' * length for length in max_lengths])
|
if width > col_width[i]:
|
||||||
hline += '+\n'
|
col_width[i] = width
|
||||||
info = hline
|
# prepare vline.
|
||||||
for i, row in enumerate(table):
|
vline = []
|
||||||
info += '|'
|
colaligns = []
|
||||||
row_just = []
|
col_pos = 0
|
||||||
align = h_align if i <= header_line else c_align
|
line_delemeter = '-'
|
||||||
for w, col, a in zip(max_lengths, row, align):
|
content_delemeter = ' '
|
||||||
if a == 'c':
|
for ch in colsty:
|
||||||
row_just.append(col.center(w))
|
if ch == '|':
|
||||||
elif a == 'l':
|
vline.append('+')
|
||||||
row_just.append(col.ljust(w))
|
elif ch in ['c', 'l', 'r']:
|
||||||
elif a == 'r':
|
colaligns.append(ch)
|
||||||
row_just.append(col.rjust(w))
|
vline.append('-' * col_width[col_pos])
|
||||||
info += delemeter.join(row_just)
|
col_pos += 1
|
||||||
info += '|\n'
|
vline = line_delemeter.join(vline)
|
||||||
if i == header_line:
|
table_to_draw = []
|
||||||
info += hline
|
row_pos = 0
|
||||||
info += hline
|
for ch in rowsty:
|
||||||
return info
|
if ch == '|':
|
||||||
|
table_to_draw.append("vline")
|
||||||
|
elif ch in ['c', 'l', 'r']:
|
||||||
|
table_to_draw.append(table[row_pos])
|
||||||
|
row_pos += 1;
|
||||||
|
strings = []
|
||||||
|
for row in table_to_draw:
|
||||||
|
if type(row) is str:
|
||||||
|
strings.append(vline)
|
||||||
|
continue
|
||||||
|
new_row = []
|
||||||
|
max_cols = 1
|
||||||
|
for word, align, width in zip(row, colaligns, col_width):
|
||||||
|
cols = []
|
||||||
|
lines = word.split('\n')
|
||||||
|
for line in lines:
|
||||||
|
while len(line) > 0:
|
||||||
|
cols.append(line[:width])
|
||||||
|
line = line[width:]
|
||||||
|
cols = [justify(col, align, width) for col in cols]
|
||||||
|
if len(cols) > max_cols:
|
||||||
|
max_cols = len(cols)
|
||||||
|
new_row.append(cols)
|
||||||
|
for cols, width in zip(new_row, col_width):
|
||||||
|
empty = ' ' * width
|
||||||
|
while len(cols) < max_cols:
|
||||||
|
cols.append(empty)
|
||||||
|
rows = list(zip(*new_row))
|
||||||
|
for row in rows:
|
||||||
|
cols_to_drawn = []
|
||||||
|
col_pos = 0
|
||||||
|
for ch in colsty:
|
||||||
|
if ch == '|':
|
||||||
|
cols_to_drawn.append('|')
|
||||||
|
elif ch in ['c', 'r', 'l']:
|
||||||
|
cols_to_drawn.append(row[col_pos])
|
||||||
|
col_pos += 1
|
||||||
|
strings.append(content_delemeter.join(cols_to_drawn))
|
||||||
|
return '\n'.join(strings)
|
||||||
|
|
||||||
class GPUStat():
|
class GPUStat():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -239,15 +283,18 @@ class GPUStat():
|
|||||||
value = [value]
|
value = [value]
|
||||||
self.detailed_info[key] = [parse_gpu_info(info) for info in value]
|
self.detailed_info[key] = [parse_gpu_info(info) for info in value]
|
||||||
self.process_info = self.get_process_info()
|
self.process_info = self.get_process_info()
|
||||||
self.simplified_info = {
|
self.simplified_info = {}
|
||||||
"driver_version": self.detailed_info["driver_version"],
|
for key in self.detailed_info:
|
||||||
"cuda_version": self.detailed_info["cuda_version"],
|
if key != "gpu":
|
||||||
"attached_gpus": self.detailed_info["attached_gpus"],
|
self.simplified_info[key] = self.detailed_info[key]
|
||||||
"gpus": [simplify_gpu_info(stat) for stat in self.detailed_info["gpu"]]
|
else:
|
||||||
}
|
self.simplified_info["gpus"] = [simplify_gpu_info(stat) for stat in self.detailed_info["gpu"]]
|
||||||
self.cuda_version = self.simplified_info["cuda_version"]
|
if "cuda_version" in self.simplified_info:
|
||||||
self.driver_version = self.simplified_info["driver_version"]
|
self.cuda_version = self.simplified_info["cuda_version"]
|
||||||
self.attached_gpus = self.simplified_info["attached_gpus"]
|
if "driver_version" in self.simplified_info:
|
||||||
|
self.driver_version = self.simplified_info["driver_version"]
|
||||||
|
if "attached_gpus" in self.simplified_info:
|
||||||
|
self.attached_gpus = self.simplified_info["attached_gpus"]
|
||||||
self.gpus = []
|
self.gpus = []
|
||||||
for i, gpu in enumerate(self.simplified_info["gpus"]):
|
for i, gpu in enumerate(self.simplified_info["gpus"]):
|
||||||
for process in gpu['processes']:
|
for process in gpu['processes']:
|
||||||
@@ -255,7 +302,7 @@ class GPUStat():
|
|||||||
gpu['id'] = i
|
gpu['id'] = i
|
||||||
self.gpus.append(gpu)
|
self.gpus.append(gpu)
|
||||||
|
|
||||||
def show(self, enabled_cols = ['ID', 'Fan', 'Temp', 'Pwr', 'Freq', 'Util', 'Vmem', 'Users'], show_command=True):
|
def show(self, enabled_cols = ['ID', 'Fan', 'Temp', 'Pwr', 'Freq', 'Util', 'Vmem', 'Users'], colsty=None, colsz=None, show_command=True, vertical=False):
|
||||||
self.parse()
|
self.parse()
|
||||||
gpu_infos = []
|
gpu_infos = []
|
||||||
# stats = {
|
# stats = {
|
||||||
@@ -273,11 +320,23 @@ class GPUStat():
|
|||||||
# "mem_free": stat['memory']['free'].split(' ')[0].strip()
|
# "mem_free": stat['memory']['free'].split(' ')[0].strip()
|
||||||
# }
|
# }
|
||||||
for gpu in self.gpus:
|
for gpu in self.gpus:
|
||||||
process_fmt = '{user}({pid})'
|
# process_fmt = '{user}({pid})'
|
||||||
process_info = ','.join([process_fmt.format(
|
# process_info = ','.join([process_fmt.format(
|
||||||
user = proc['user'],
|
# user = proc['user'],
|
||||||
|
# pid = proc['pid']
|
||||||
|
# ) for proc in gpu['processes']])
|
||||||
|
process_fmt = '{user}({pids})'
|
||||||
|
users_process = {}
|
||||||
|
for proc in gpu['processes']:
|
||||||
|
user = proc['user']
|
||||||
pid = proc['pid']
|
pid = proc['pid']
|
||||||
) for proc in gpu['processes']])
|
if user not in users_process:
|
||||||
|
users_process[user] = []
|
||||||
|
users_process[user].append(pid)
|
||||||
|
delemeter = ','
|
||||||
|
if vertical:
|
||||||
|
delemeter = '\n'
|
||||||
|
process_info = delemeter.join(process_fmt.format(user=user, pids = '|'.join(users_process[user])) for user in users_process)
|
||||||
info_gpu = {
|
info_gpu = {
|
||||||
'ID': '{0}'.format(str(gpu['id'])),
|
'ID': '{0}'.format(str(gpu['id'])),
|
||||||
'Fan': '{0} %'.format(gpu['fan_speed'].split(' ')[0].strip()),
|
'Fan': '{0} %'.format(gpu['fan_speed'].split(' ')[0].strip()),
|
||||||
@@ -307,29 +366,34 @@ class GPUStat():
|
|||||||
for info in gpu_infos:
|
for info in gpu_infos:
|
||||||
this_row = [info[key] for key in enabled_cols]
|
this_row = [info[key] for key in enabled_cols]
|
||||||
info_table.append(this_row)
|
info_table.append(this_row)
|
||||||
info = draw_table(info_table, header_line=0, delemeter=' | ', joint_delemeter='-+-', c_align=c_align)
|
info = draw_table(info_table, rowsty='|c|{0}|'.format('c'*(len(info_table)-1)), colsty=colsty, colsz=colsz) + '\n'
|
||||||
if show_command:
|
if show_command:
|
||||||
procs = {}
|
procs = {}
|
||||||
for gpu in self.gpus:
|
for gpu in self.gpus:
|
||||||
for proc in gpu['processes']:
|
for proc in gpu['processes']:
|
||||||
pid = proc['pid']
|
pid = proc['pid']
|
||||||
proc['gpu'] = [str(gpu['id'])]
|
proc['gpu'] = [str(gpu['id'])]
|
||||||
|
if type(proc['vmem']) is str:
|
||||||
|
proc['vmem'] = int(proc['vmem'].split(' ')[0])
|
||||||
if pid not in procs:
|
if pid not in procs:
|
||||||
procs[pid] = proc
|
procs[pid] = proc
|
||||||
else:
|
else:
|
||||||
procs[pid]['gpu'].append(str(gpu['id']))
|
procs[pid]['gpu'].append(str(gpu['id']))
|
||||||
|
procs[pid]['vmem'] += proc['vmem']
|
||||||
proc_fmt = '[{pid}|{gpus}] {user}({vmem} MiB) {cmd}'
|
proc_fmt = '[{pid}|{gpus}] {user}({vmem} MiB) {cmd}'
|
||||||
proc_strs = []
|
proc_strs = []
|
||||||
for pid in procs:
|
for pid in procs:
|
||||||
this_proc_str = proc_fmt.format(
|
this_proc_str = proc_fmt.format(
|
||||||
user = procs[pid]['user'],
|
user = procs[pid]['user'],
|
||||||
vmem = procs[pid]['vmem'].split(' ')[0],
|
vmem = procs[pid]['vmem'],
|
||||||
pid = procs[pid]['pid'].rjust(5),
|
pid = procs[pid]['pid'].rjust(5),
|
||||||
cmd = procs[pid]['command'],
|
cmd = procs[pid]['command'],
|
||||||
gpus = ','.join(procs[pid]['gpu'])
|
gpus = ','.join(procs[pid]['gpu'])
|
||||||
)
|
)
|
||||||
proc_strs.append(this_proc_str)
|
proc_strs.append(this_proc_str)
|
||||||
proc_info = '\n'.join(proc_strs)
|
proc_info = '\n'.join(proc_strs)
|
||||||
|
table_width = info.find('\n')
|
||||||
|
proc_info = draw_table([['Process Info'.center(table_width-4)], [proc_info]], rowsty="c|c|", colsty="|l|", colsz=[table_width-4])
|
||||||
info += proc_info
|
info += proc_info
|
||||||
print(info)
|
print(info)
|
||||||
|
|
||||||
|
|||||||
2
setup.py
2
setup.py
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
|
|||||||
|
|
||||||
setup(
|
setup(
|
||||||
name = 'gpuutil',
|
name = 'gpuutil',
|
||||||
version = '0.0.2',
|
version = '0.0.3',
|
||||||
keywords='gpu utils',
|
keywords='gpu utils',
|
||||||
description = 'A tool for observing gpu stat and auto set visible gpu in python code.',
|
description = 'A tool for observing gpu stat and auto set visible gpu in python code.',
|
||||||
license = 'MIT License',
|
license = 'MIT License',
|
||||||
|
|||||||
Reference in New Issue
Block a user