diff --git a/src/plotman/configuration.py b/src/plotman/configuration.py index df03e143..e3672e34 100644 --- a/src/plotman/configuration.py +++ b/src/plotman/configuration.py @@ -1,11 +1,13 @@ import contextlib import importlib +import itertools import os import stat import subprocess import tempfile import textwrap -from typing import Dict, Generator, List, Mapping, Optional +from collections.abc import Iterator +from typing import Any, cast, Dict, Generator, Iterable, List, Mapping, Optional import appdirs import attr @@ -292,11 +294,24 @@ def _create_log_path(self, time: pendulum.DateTime, directory: str, group: str) timestamp = time.isoformat(timespec='microseconds').replace(':', '_') return os.path.join(directory, f'{timestamp}.{group}.log') -@attr.frozen +@attr.mutable class Directories: tmp: List[str] dst: Optional[List[str]] = None - tmp2: Optional[str] = None + tmp2: Optional[List[str]] = None + x: Any = None + y: Any = '' + + def next_tmp2(self) -> None: + assert self.tmp2 is not None + if self.x is None: + self.x = itertools.cycle(self.tmp2) + + assert self.x is not None + self.y = next(self.x) + + def get_tmp2(self) -> str: + return self.y def dst_is_tmp(self) -> bool: return self.dst is None and self.tmp2 is None diff --git a/src/plotman/madmax.py b/src/plotman/madmax.py index a4a2e026..89994311 100644 --- a/src/plotman/madmax.py +++ b/src/plotman/madmax.py @@ -71,5 +71,7 @@ def latest_command(self) -> CommandProtocol: type=str, default=None) @click.option("-G", "--tmptoggle", help="Alternate tmpdir/tmpdir2", type=str, default=None) +@click.option("-K", "--rmulti2", help="Thread multiplier for P2 (default = 1)", + type=int, default=1) def _cli_c8121b9() -> None: pass diff --git a/src/plotman/manager.py b/src/plotman/manager.py index a199dacf..e396a4b9 100644 --- a/src/plotman/manager.py +++ b/src/plotman/manager.py @@ -116,9 +116,11 @@ def maybe_start_new_plot(dir_cfg: plotman.configuration.Directories, sched_cfg: dst_dirs = dir_cfg.get_dst_directories() + dir_cfg.next_tmp2() + dstdir: str if dir_cfg.dst_is_tmp2(): - dstdir = dir_cfg.tmp2 # type: ignore[assignment] + dstdir = dir_cfg.get_tmp2() elif tmpdir in dst_dirs: dstdir = tmpdir elif dir_cfg.dst_is_tmp(): @@ -146,14 +148,15 @@ def key(key: str) -> job.Phase: ) plot_args = [ plotting_cfg.madmax.executable, + '-K', str(2), '-n', str(1), '-r', str(plotting_cfg.madmax.n_threads), '-u', str(plotting_cfg.madmax.n_buckets), '-t', tmpdir if tmpdir.endswith('/') else (tmpdir + '/'), '-d', dstdir if dstdir.endswith('/') else (dstdir + '/') ] - if dir_cfg.tmp2 is not None: + if dir_cfg.get_tmp2() is not None: plot_args.append('-2') - plot_args.append(dir_cfg.tmp2 if dir_cfg.tmp2.endswith('/') else (dir_cfg.tmp2 + '/')) + plot_args.append(dir_cfg.get_tmp2() if dir_cfg.get_tmp2().endswith('/') else (dir_cfg.get_tmp2() + '/')) else: if plotting_cfg.chia is None: raise Exception( @@ -170,9 +173,9 @@ def key(key: str) -> job.Phase: plot_args.append('-e') if plotting_cfg.chia.x: plot_args.append('-x') - if dir_cfg.tmp2 is not None: + if dir_cfg.get_tmp2() is not None: plot_args.append('-2') - plot_args.append(dir_cfg.tmp2) + plot_args.append(dir_cfg.get_tmp2()) if plotting_cfg.farmer_pk is not None: plot_args.append('-f') plot_args.append(plotting_cfg.farmer_pk) @@ -222,6 +225,10 @@ def key(key: str) -> job.Phase: creationflags = 0 nice = 15 + node = dir_cfg.get_tmp2().rstrip('/')[-1] + + plot_args = ['numactl', f'--membind={node}', f'--cpunodebind={node}', '--', *plot_args] + with open_log_file: # start_new_sessions to make the job independent of this controlling tty (POSIX only). # subprocess.CREATE_NO_WINDOW to make the process independent of this controlling tty and have no console window on Windows. diff --git a/src/plotman/reporting.py b/src/plotman/reporting.py index 8641d63b..83aef5eb 100644 --- a/src/plotman/reporting.py +++ b/src/plotman/reporting.py @@ -138,6 +138,7 @@ def prometheus_report(jobs: typing.List[job.Job], tmp_prefix: str = '', dst_pref metrics = { 'plotman_plot_phase_major': 'The phase the plot is currently in', 'plotman_plot_phase_minor': 'The part of the phase the plot is currently in', + 'plotman_plot_phase_major_minor': 'major and minor', 'plotman_plot_tmp_usage': 'Tmp dir usage in bytes', 'plotman_plot_mem_usage': 'Memory usage in bytes', 'plotman_plot_user_time': 'Processor time (user) in s', @@ -155,8 +156,9 @@ def prometheus_report(jobs: typing.List[job.Job], tmp_prefix: str = '', dst_pref } label_str = ','.join([f'{k}="{v}"' for k, v in labels.items()]) values = { - 'plotman_plot_phase_major': j.progress().major, - 'plotman_plot_phase_minor': j.progress().minor, + 'plotman_plot_phase_major': j.progress().major if j.progress().known else 0, + 'plotman_plot_phase_minor': j.progress().minor if j.progress().known else 0, + 'plotman_plot_phase_major_minor': j.progress().major + (j.progress().minor / 10) if j.progress().known else 0, 'plotman_plot_tmp_usage': j.get_tmp_usage(), 'plotman_plot_mem_usage': j.get_mem_usage(), 'plotman_plot_user_time': j.get_time_user(),