added Planned_Time and Elig_Time
This commit is contained in:
+43
-21
@@ -42,10 +42,10 @@ from typing import Any, Iterable, Mapping
|
||||
import msgpack
|
||||
import gzip
|
||||
|
||||
VERSION=0.21
|
||||
VERSION=0.22
|
||||
|
||||
# Default GB per CPUs for the cluster
|
||||
default_mempercpu_gb = 2.0
|
||||
default_mempercpu_gb = 2.2
|
||||
|
||||
SACCT_FIELDS = [
|
||||
"JobIDRaw",
|
||||
@@ -64,6 +64,7 @@ SACCT_FIELDS = [
|
||||
"ReqTRes",
|
||||
"AllocTRES",
|
||||
"TRESUsageInTot",
|
||||
"PlannedCPURAW"
|
||||
]
|
||||
|
||||
ALL_COLUMNS = [
|
||||
@@ -82,6 +83,8 @@ ALL_COLUMNS = [
|
||||
"MaxRSS_max",
|
||||
"MemPerCPU",
|
||||
"Mem_Eff",
|
||||
"Planned_Time",
|
||||
"Elig_Qtime",
|
||||
"waste_Mem",
|
||||
"ReqWalltime",
|
||||
"Walltime",
|
||||
@@ -134,6 +137,8 @@ PRESET_COLUMNS = {
|
||||
"Walltime",
|
||||
"Walltime_max",
|
||||
"Time_Eff",
|
||||
# "Planned_Time",
|
||||
"Elig_Qtime",
|
||||
"jobname",],
|
||||
"cpu": [
|
||||
"username",
|
||||
@@ -208,6 +213,7 @@ NUMERIC_COLUMNS = {
|
||||
"AllocMem",
|
||||
"UsedMem",
|
||||
"MemPerCPU",
|
||||
"Elig_Qtime",
|
||||
"ReqWalltime",
|
||||
"Count",
|
||||
"CPU_Eff",
|
||||
@@ -361,9 +367,11 @@ class JobRecord:
|
||||
mem_per_cpu_gb: float | None
|
||||
mem_alloc_tres: float | None
|
||||
mem_used_tres: float | None
|
||||
planned_sec: float
|
||||
reqwall_hours: float | None
|
||||
reqmem_bytes_total: float | None
|
||||
elapsed_sec: int
|
||||
elig_qtime_sec: float
|
||||
timelimit_sec: int
|
||||
totalcpu_sec: float
|
||||
maxrss_bytes: float | None
|
||||
@@ -437,6 +445,8 @@ class OutputRow:
|
||||
UsedMem: float | None
|
||||
MemPerCPU: float | None
|
||||
ReqWalltime: float | None
|
||||
Planned_Time: float | None
|
||||
Elig_Qtime: float | None
|
||||
Count: int
|
||||
CPU_Eff: float | None
|
||||
Mem_Eff: float | None
|
||||
@@ -468,6 +478,8 @@ class OutputRow:
|
||||
"ReqWalltime": self.ReqWalltime,
|
||||
"Walltime": self.walltime,
|
||||
"Walltime_max": self.walltime_max,
|
||||
"Elig_Qtime": self.Elig_Qtime,
|
||||
"Planned_Time": self.Planned_Time,
|
||||
"Count": self.Count,
|
||||
"CPU_Eff": self.CPU_Eff,
|
||||
"Mem_Eff": self.Mem_Eff,
|
||||
@@ -780,6 +792,8 @@ def build_job_records(rows: list[dict[str, str]]) -> list[JobRecord]:
|
||||
continue
|
||||
nodes = int(float(top.get("NNodes") or 0))
|
||||
elapsed = int(float(top.get("ElapsedRaw") or 0))
|
||||
planned_sec = float(top.get("PlannedCPURAW") or 0)
|
||||
elig_qtime_sec = planned_sec / alloc_cpus
|
||||
|
||||
# sacct TimelimitRaw is minutes, while ElapsedRaw and CPUTimeRAW are seconds.
|
||||
timelimit_raw_minutes = float(top.get("TimelimitRaw") or 0)
|
||||
@@ -838,9 +852,11 @@ def build_job_records(rows: list[dict[str, str]]) -> list[JobRecord]:
|
||||
mem_used_tres=mem_used_tres_gb,
|
||||
mem_per_cpu_gb=mem_per_cpu_gb,
|
||||
mem_alloc_tres=mem_alloc_tres_gb,
|
||||
planned_sec=planned_sec,
|
||||
reqwall_hours=reqwall_hours,
|
||||
reqmem_bytes_total=reqmem_total,
|
||||
elapsed_sec=elapsed,
|
||||
elig_qtime_sec=elig_qtime_sec,
|
||||
timelimit_sec=timelimit_seconds,
|
||||
totalcpu_sec=totalcpu,
|
||||
maxrss_bytes=maxrss,
|
||||
@@ -923,6 +939,8 @@ def make_single_row(rec: JobRecord, dflt_mpcpu: float) -> OutputRow:
|
||||
"""Returns an OutputRow based on a single slurm job record."""
|
||||
walltime = rec.elapsed_sec / 3600
|
||||
|
||||
# TODO elig_qtime_sec = rec.
|
||||
|
||||
waste_mem = 0
|
||||
if rec.mem_eff is not None and rec.reqmem_gb is not None:
|
||||
waste_mem = max(0,walltime * (100-rec.mem_eff)/100 \
|
||||
@@ -954,6 +972,8 @@ def make_single_row(rec: JobRecord, dflt_mpcpu: float) -> OutputRow:
|
||||
UsedMem=rec.mem_used_tres,
|
||||
MemPerCPU=rec.mem_per_cpu_gb,
|
||||
ReqWalltime=rec.reqwall_hours,
|
||||
Planned_Time=rec.planned_sec/3600,
|
||||
Elig_Qtime=rec.elig_qtime_sec/3600,
|
||||
Count=1,
|
||||
CPU_Eff=rec.cpu_eff,
|
||||
Mem_Eff=rec.mem_eff,
|
||||
@@ -983,6 +1003,11 @@ def make_aggregate_row(records: list[JobRecord], username: str,
|
||||
if walltime is not None:
|
||||
walltime /= 3600
|
||||
|
||||
planned_sec = mean_or_none([r.planned_sec for r in records
|
||||
if r.planned_sec is not None])
|
||||
elig_qtime_sec = mean_or_none([r.elig_qtime_sec for r in records
|
||||
if r.elig_qtime_sec is not None])
|
||||
|
||||
# We average over all jobs' allocated memory. Some jobs could have received
|
||||
# different allocations, even though all of them had the same user required
|
||||
# Memory. Maybe should generate a warning. Most of the time, what the user
|
||||
@@ -1023,6 +1048,8 @@ def make_aggregate_row(records: list[JobRecord], username: str,
|
||||
UsedMem=used_mem,
|
||||
MemPerCPU=first.mem_per_cpu_gb,
|
||||
ReqWalltime=first.reqwall_hours,
|
||||
Planned_Time=planned_sec/3600,
|
||||
Elig_Qtime=elig_qtime_sec/3600,
|
||||
Count=count,
|
||||
CPU_Eff=cpu_efficiency,
|
||||
Mem_Eff=memory_efficiency,
|
||||
@@ -1096,28 +1123,15 @@ def columns_for_sdev(base_cols: list[str]) -> list[str]:
|
||||
return out
|
||||
|
||||
|
||||
|
||||
|
||||
def format_gb_value(value: float | None) -> str:
|
||||
if value is None:
|
||||
return "NA"
|
||||
return f"{value:.2f}G"
|
||||
|
||||
|
||||
def format_secs_to_hours(value: float | None) -> str:
|
||||
if value is None:
|
||||
return "NA"
|
||||
return f"{value:.2f}h"
|
||||
|
||||
|
||||
def format_value(value: Any, column: str | None = None) -> str:
|
||||
if column in ["ReqMem", "UsedMem","MemPerCPU", "MaxRSS_max", "AllocMem"]:
|
||||
return format_gb_value(value)
|
||||
if column in ["ReqWalltime", "Walltime", "Walltime_max"]:
|
||||
return format_secs_to_hours(value)
|
||||
|
||||
if value is None:
|
||||
return "NA"
|
||||
if column in ["ReqMem", "UsedMem","MemPerCPU", "MaxRSS_max", "AllocMem"]:
|
||||
return f"{value:.2f}G"
|
||||
if column in ["ReqWalltime", "Walltime", "Walltime_max",
|
||||
"Elig_Qtime", "Planned_Time"]:
|
||||
return f"{value:.2f}h"
|
||||
|
||||
if isinstance(value, float):
|
||||
return f"{value:.2f}"
|
||||
return str(value)
|
||||
@@ -1233,6 +1247,14 @@ def main(argv: list[str] | None = None) -> int:
|
||||
show_cache_info(args.info)
|
||||
sys.exit(0)
|
||||
|
||||
if args.write_binary_cache and os.path.exists(args.write_binary_cache):
|
||||
sys.stderr.write(f"WARNING, file exists: {args.write_binary_cache}. Balking out...\n")
|
||||
sys.exit(1)
|
||||
if args.output_raw and os.path.exists(args.output_raw):
|
||||
sys.stderr.write(f"WARNING, file exists: {args.output_raw}. Balking out...\n")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
output_columns = PRESET_COLUMNS["default"]
|
||||
if args.preset:
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user