nodeocc 1.0.2__tar.gz → 1.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {nodeocc-1.0.2 → nodeocc-1.0.3}/PKG-INFO +1 -1
  2. {nodeocc-1.0.2 → nodeocc-1.0.3}/pyproject.toml +1 -1
  3. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/model/infrastructure.py +1 -1
  4. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/PKG-INFO +1 -1
  5. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/readers/slurmreader.py +43 -25
  6. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/curses_multiwindow.py +1 -1
  7. {nodeocc-1.0.2 → nodeocc-1.0.3}/README.md +0 -0
  8. {nodeocc-1.0.2 → nodeocc-1.0.3}/setup.cfg +0 -0
  9. {nodeocc-1.0.2 → nodeocc-1.0.3}/setup.py +0 -0
  10. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/__init__.py +0 -0
  11. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/controller/controller.py +0 -0
  12. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/model/job.py +0 -0
  13. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/SOURCES.txt +0 -0
  14. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/dependency_links.txt +0 -0
  15. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/entry_points.txt +0 -0
  16. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/requires.txt +0 -0
  17. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/nodeocc.egg-info/top_level.txt +0 -0
  18. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/readers/compute_wait_time.py +0 -0
  19. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/__init__.py +0 -0
  20. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/slurm_list.py +0 -0
  21. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/slurm_viz.py +0 -0
  22. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/styles.py +0 -0
  23. {nodeocc-1.0.2 → nodeocc-1.0.3}/src/view/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: TUI application for viewing the status of GPU allocations on a Slurm cluster
5
5
  Author: Matteo Boschini
6
6
  Maintainer: Lorenzo Bonicelli, Aniello Panariello
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "nodeocc"
7
- version = "1.0.2"
7
+ version = "1.0.3"
8
8
  authors = [{ name = "Matteo Boschini" }]
9
9
  maintainers = [{ name = "Lorenzo Bonicelli" }, { name = "Aniello Panariello" }]
10
10
  description = "TUI application for viewing the status of GPU allocations on a Slurm cluster"
@@ -67,7 +67,7 @@ class Infrastructure:
67
67
  self.cpu_limit_grp = cpu_limit_grp
68
68
  self.cpu_limit_stu = cpu_limit_stu
69
69
  self.cpu_limit_stugrp = cpu_limit_stugrp
70
- self.prior = ['n/a', None, 'RTXA5000', 'RTX6000', 'RTX5000', '2080', 'V100', '1080', 'P100', 'K80']
70
+ self.prior = ['n/a', None, 'A40', 'RTXA5000', 'RTX6000', 'RTX5000', '2080', 'V100', '1080', 'P100', 'K80']
71
71
 
72
72
  @staticmethod
73
73
  def from_dict(d):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: nodeocc
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: TUI application for viewing the status of GPU allocations on a Slurm cluster
5
5
  Author: Matteo Boschini
6
6
  Maintainer: Lorenzo Bonicelli, Aniello Panariello
@@ -1,6 +1,5 @@
1
- import json
2
1
  import os
3
- import time
2
+ import re
4
3
  from io import StringIO
5
4
 
6
5
  import pandas as pd
@@ -152,27 +151,27 @@ def _load_joblet_meta(line):
152
151
 
153
152
 
154
153
  def _gpus_per_joblet(line):
155
- if pd.isna(line['gpus_per_job']) and pd.isna(line['gpus_per_node']) and pd.isna(line['gpus_per_task']):
154
+ if pd.isna(line['ALL_JOB_NODES']):
156
155
  return 0
157
- elif not pd.isna(line['gpus_per_node']):
158
- return line['gpus_per_node'] * (line['NODES'] if pd.isna(line['NODELIST']) else 1)
156
+ if line['ALL_JOB_NODES'].count(',') == 0:
157
+ return line['TRES_ALLOC'].split('gpu=')[-1].split(',')[0] if 'gpu=' in line['TRES_ALLOC'] else 0
159
158
  else:
160
- if line['ST'] == 'PD':
161
- return line['gpus_per_job'] if not pd.isna(line['gpus_per_job']) else line['gpus_per_task']
162
- gpus_id = line['joblet_meta_str']
163
- gpus_id = sum([x.split('IDX:')[-1].split(')')[0].split(',') for x in gpus_id if 'gpu' in x], [])
164
- gpus_n = len(gpus_id) + sum([len(range(int(x.split('-')[1].split()[0]) - int(x.split('-')[0]))) for x in gpus_id if '-' in x])
165
- return gpus_n
159
+ node = line['NODELIST']
160
+ node_idx = line['ALL_JOB_NODES'].split(',').index(node)
161
+ return int(re.findall(r'gpu:(\d+)', line['TRES_PER_NODE'])[node_idx]) if 'gpu:' in line['TRES_PER_NODE'] else 0
166
162
 
167
163
 
168
164
  def _cpus_per_joblet(line):
169
- if line['ST'] == 'PD':
170
- return line['MIN_CPUS']
165
+ if pd.isna(line['ALL_JOB_NODES']):
166
+ return 0
167
+ if line['ALL_JOB_NODES'].count(',') == 0:
168
+ return int(str(line['TRES_ALLOC']).split('cpu=')[-1].split(',')[0])
171
169
  else:
172
- cpus_id = line['joblet_meta_str']
173
- cpus = sum([x.split('CPU_IDs=')[-1].split()[0].split(',') for x in cpus_id], [])
174
- cpus_n = len(cpus) + sum([len(range(int(x.split('-')[1].split()[0]) - int(x.split('-')[0]))) for x in cpus if '-' in x])
175
- return cpus_n
170
+ nodes = line['NODES']
171
+ tot_gpu = int(str(line['TRES_ALLOC']).split('gpu=')[-1].split(',')[0]) if 'gpu=' in str(line['TRES_ALLOC']) else 0
172
+ tot_cpus = int(str(line['TRES_ALLOC']).split('cpu=')[-1].split(',')[0])
173
+ n_gpus = line['joblet_gpus']
174
+ return int(tot_cpus) // int(nodes) if tot_gpu == 0 else int(tot_cpus) // tot_gpu * n_gpus
176
175
 
177
176
 
178
177
  memunits = {
@@ -193,12 +192,26 @@ def parse_mem(thing):
193
192
 
194
193
 
195
194
  def _mem_per_joblet(line):
196
- if line['ST'] == 'PD':
197
- return parse_mem(line['MIN_MEMORY'])
198
- else:
199
- mem_id = line['joblet_meta_str']
200
- mem = sum([int(x.split('Mem=')[-1].split()[0]) for x in mem_id])
195
+ if pd.isna(line['ALL_JOB_NODES']):
196
+ return 0
197
+ try:
198
+ mem = line['TRES_ALLOC'].split('mem=')[-1].split(',')[0]
199
+ if 'G' in mem:
200
+ mem = int(mem.split('G')[0]) * 1024
201
+ elif 'M' in mem:
202
+ mem = int(mem.split('M')[0])
203
+ else:
204
+ mem = int(mem)
205
+ except BaseException:
206
+ return 0
207
+
208
+ if line['ALL_JOB_NODES'].count(',') == 0:
201
209
  return mem
210
+ else:
211
+ nodes = line['NODES']
212
+ tot_gpu = int(str(line['TRES_ALLOC']).split('gpu=')[-1].split(',')[0]) if 'gpu=' in str(line['TRES_ALLOC']) else 0
213
+ n_gpus = line['joblet_gpus']
214
+ return int(mem) // int(nodes) if tot_gpu == 0 else int(mem) // tot_gpu * n_gpus
202
215
 
203
216
 
204
217
  def _true_jobid(line):
@@ -257,15 +270,20 @@ def read_jobs():
257
270
  instance.timeme(f"\t- squeue and dataframe creation")
258
271
 
259
272
  squeue_df['JOBID'] = squeue_df['JOBID'].apply(str)
273
+ squeue_df['ALL_JOB_NODES'] = squeue_df['NODELIST']
260
274
  squeue_df = _split_column(squeue_df, 'NODELIST')
275
+
261
276
  squeue_df['gpus_per_node'] = squeue_df['TRES_PER_NODE'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
262
277
  squeue_df['gpus_per_job'] = squeue_df['TRES_PER_JOB'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
263
278
  squeue_df['gpus_per_task'] = squeue_df['TRES_PER_TASK'].apply(lambda x: try_parse_gpu(x) if isinstance(x, str) else x)
264
279
 
265
280
  try:
266
- squeue_df['joblet_mem'] = squeue_df['TRES_ALLOC'].apply(get_mem_joblet)
267
- squeue_df['joblet_gpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: str(l).split('gpu=')[-1].split(',')[0] if 'gpu=' in str(l) else 0)
268
- squeue_df['joblet_cpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: int(str(l).split('cpu=')[-1].split(',')[0]))
281
+ # squeue_df['joblet_gpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: str(l).split('gpu=')[-1].split(',')[0] if 'gpu=' in str(l) else 0)
282
+ squeue_df['joblet_gpus'] = squeue_df.apply(_gpus_per_joblet, axis=1)
283
+ # squeue_df['joblet_cpus'] = squeue_df['TRES_ALLOC'].apply(lambda l: int(str(l).split('cpu=')[-1].split(',')[0]))
284
+ squeue_df['joblet_cpus'] = squeue_df.apply(_cpus_per_joblet, axis=1)
285
+ # squeue_df['joblet_mem'] = squeue_df['TRES_ALLOC'].apply(get_mem_joblet)
286
+ squeue_df['joblet_mem'] = squeue_df.apply(_mem_per_joblet, axis=1)
269
287
  except Exception as e:
270
288
  instance.err(f"Exception PD: {e}")
271
289
 
@@ -89,7 +89,7 @@ class Singleton:
89
89
  self.basepath = self.args.basepath
90
90
 
91
91
  if self.args.daemon_only:
92
- handler = RotatingFileHandler(os.path.join(self.basepath, '.master_log_n.txt'), maxBytes=5 * 1024 * 1024, backupCount=2, mode='w')
92
+ handler = RotatingFileHandler(os.path.join(self.basepath, '.master_log.txt'), maxBytes=5 * 1024 * 1024, backupCount=2, mode='w')
93
93
  logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(message)s', datefmt='%d-%b-%y %H:%M:%S',
94
94
  handlers=[handler])
95
95
  # set logging file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes