-
Notifications
You must be signed in to change notification settings - Fork 3
Worker for overflow queue #763
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a72c2b0
cbd8aa6
2ad819e
fc5f199
293adc3
07e8409
1220868
7dbf1ed
62c4c91
7786585
36b0b47
90ac694
e5ddb24
1cc7044
b42dd06
02f0ce7
2804562
6fb86f7
ff10b0d
38e0220
7138878
88d623b
a9c4c68
0e60b28
faf4c50
4bd0001
cf1cfe9
3887d16
a519306
b3ab3a2
3936620
a9f4eea
6fb2dec
ef7f5bf
199d3d8
18e2b01
15b69d2
fc7a382
7a3b191
4033bf3
ed922cd
1c3e263
cea4ca1
35a9372
17f1c3a
acd91fe
337fa45
19e4cbf
9053074
495fcb4
5362c73
1b4baa9
0855ee9
8cb53ca
03c0772
3593ed9
79842e6
8551eda
a969dd9
928465b
4eed8e3
3e36a5a
eb134dc
ad6ca17
f1d0aff
27bad49
88d0cd6
68b1408
1458079
e2f01fe
095385f
ae7ac00
78aa031
c7f9eaf
d4babd8
72da39d
60e2dee
dbf3e65
6b73ab7
fd9b630
b60d3a2
c27713f
d66d78d
a647574
4e097b6
1c0148a
62d4898
dba3b48
ad4e45c
6248561
1e2d21c
10db91c
8daa42c
77ae767
54c5a23
676b4ec
9b497d2
6c624bd
6c02845
5f7b676
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,248 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import hashlib | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import os | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from time import sleep | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from typing import Callable, Optional | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from pysqa import QueueAdapter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from executorlib.standalone.inputcheck import validate_number_of_cores | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from executorlib.standalone.interactive.spawner import BaseSpawner | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from executorlib.standalone.scheduler import pysqa_execute_command, terminate_with_pysqa | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| from executorlib.task_scheduler.interactive.blockallocation import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BlockAllocationTaskScheduler, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class PysqaSpawner(BaseSpawner): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cwd: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores: int = 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| threads_per_core: int = 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gpus_per_core: int = 0, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| num_nodes: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclusive: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openmpi_oversubscribe: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| slurm_cmd_args: Optional[list[str]] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pmi_mode: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config_directory: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backend: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Subprocess interface implementation. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cwd (str, optional): The current working directory. Defaults to None. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores (int): The number of cores to use. Defaults to 1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| threads_per_core (int): The number of threads per core. Defaults to 1. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| gpus_per_core (int): number of GPUs per worker - defaults to 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| num_nodes (int, optional): The number of compute nodes to use for executing the task. Defaults to None. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| exclusive (bool): Whether to exclusively reserve the compute nodes, or allow sharing compute notes. Defaults | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| to False. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openmpi_oversubscribe (bool): Whether to oversubscribe the cores. Defaults to False. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| slurm_cmd_args (list, optional): Additional command line arguments for the srun call (SLURM only) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pmi_mode (str, optional): PMI interface to use (OpenMPI v5 requires pmix) default is None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config_directory (str, optional): path to the pysqa config directory (only for pysqa based backend). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backend (str): name of the backend used to spawn tasks. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| super().__init__( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cwd=cwd, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores=cores, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| openmpi_oversubscribe=openmpi_oversubscribe, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._threads_per_core = threads_per_core | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._gpus_per_core = gpus_per_core | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._num_nodes = num_nodes | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._exclusive = exclusive | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._slurm_cmd_args = slurm_cmd_args | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._pmi_mode = pmi_mode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._config_directory = config_directory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._backend = backend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._pysqa_submission_kwargs = kwargs | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._process: Optional[int] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._queue_adapter: Optional[QueueAdapter] = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def bootup( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_lst: list[str], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stop_function: Optional[Callable] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Method to start the subprocess interface. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_lst (list[str]): The command list to execute. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stop_function (Callable): Function to stop the interface. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bool: Whether the interface was successfully started. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._queue_adapter = QueueAdapter( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| directory=self._config_directory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| queue_type=self._backend, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| execute_command=pysqa_execute_command, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._process = self._start_process_helper( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_lst=command_lst, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| queue_adapter=self._queue_adapter, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| while True: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._check_process_helper(command_lst=command_lst): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif stop_function is not None and stop_function(): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.shutdown(wait=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| sleep(1) # Wait for the process to start | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def generate_command(self, command_lst: list[str]) -> list[str]: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Method to generate the command list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_lst (list[str]): The command list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| list[str]: The generated command list. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._cores > 1 and self._backend == "slurm": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend = ["srun", "-n", str(self._cores)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._pmi_mode is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["--mpi=" + self._pmi_mode] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._num_nodes is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["-N", str(self._num_nodes)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._threads_per_core > 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["--cpus-per-task=" + str(self._threads_per_core)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._gpus_per_core > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["--gpus-per-task=" + str(self._gpus_per_core)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._exclusive: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["--exact"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._openmpi_oversubscribe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["--oversubscribe"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._slurm_cmd_args is not None and len(self._slurm_cmd_args) > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += self._slurm_cmd_args | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif self._cores > 1 and self._backend == "flux": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend = ["flux", "run", "-n", str(self._cores)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._pmi_mode is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend += ["-o", "pmi=" + self._pmi_mode] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._num_nodes is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._threads_per_core > 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._gpus_per_core > 0: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._exclusive: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._openmpi_oversubscribe: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif self._cores > 1: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise ValueError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"backend should be None, slurm or flux, not {self._backend}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_prepend = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return command_prepend + command_lst | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def shutdown(self, wait: bool = True): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Method to shutdown the subprocess interface. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Args: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| wait (bool, optional): Whether to wait for the interface to shutdown. Defaults to True. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._process is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| terminate_with_pysqa( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| queue_id=self._process, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| config_directory=self._config_directory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backend=self._backend, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._process = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def poll(self) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Method to check if the subprocess interface is running. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Returns: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bool: True if the interface is running, False otherwise. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._process is not None and self._queue_adapter is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = self._queue_adapter.get_status_of_job(process_id=self._process) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return status in ["running", "pending"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _start_process_helper( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self, command_lst: list[str], queue_adapter: QueueAdapter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) -> int: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hash = hashlib.md5(str(self).encode()).hexdigest() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._cwd is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| working_directory = os.path.join(self._cwd, hash) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| working_directory = os.path.abspath(hash) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return queue_adapter.submit_job( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command=" ".join(self.generate_command(command_lst=command_lst)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| working_directory=working_directory, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores=int(self._cores * self._threads_per_core), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| **self._pysqa_submission_kwargs, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+175
to
+188
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Stop hashing into cwd; derive working_directory from cache_directory + worker_id (addresses open TODO).
- def _start_process_helper(
- self, command_lst: list[str], queue_adapter: QueueAdapter
- ) -> int:
- hash = hashlib.md5(str(self).encode()).hexdigest()
- if self._cwd is not None:
- working_directory = os.path.join(self._cwd, hash)
- else:
- working_directory = os.path.abspath(hash)
+ def _start_process_helper(
+ self, command_lst: list[str], queue_adapter: QueueAdapter
+ ) -> int:
+ # Prefer cache_directory + worker_id; fall back to a short blake2 hash
+ base_dir = (
+ self._cache_directory
+ or (self._cwd if self._cwd is not None else os.path.abspath("."))
+ )
+ if getattr(self, "_worker_id", None) is not None:
+ worker_dir = f"worker_{self._worker_id}"
+ else:
+ # stable-ish fallback without using insecure md5
+ worker_dir = "worker_" + hashlib.blake2s(
+ repr(self).encode(), digest_size=8
+ ).hexdigest()
+ working_directory = os.path.join(base_dir, worker_dir)
+ os.makedirs(working_directory, exist_ok=True)
return queue_adapter.submit_job(
command=" ".join(self.generate_command(command_lst=command_lst)),
working_directory=working_directory,
cores=int(self._cores * self._threads_per_core),
**self._pysqa_submission_kwargs,
)📝 Committable suggestion
Suggested change
🧰 Tools🪛 Ruff (0.12.2)178-178: Probable use of insecure hash functions in (S324) 🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def _check_process_helper(self, command_lst: list[str]) -> bool: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if self._queue_adapter is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = self._queue_adapter.get_status_of_job(process_id=self._process) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| status = None | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if status == "running": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return True | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif status is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise RuntimeError( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| f"Failed to start the process with command: {command_lst}" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| elif status == "error": | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._process = self._start_process_helper( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| command_lst=command_lst, queue_adapter=self._queue_adapter | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __del__(self): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self.shutdown(wait=True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def create_pysqa_block_allocation_scheduler( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_cores: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cache_directory: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| hostname_localhost: Optional[bool] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log_obj_size: bool = False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pmi_mode: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| init_function: Optional[Callable] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_workers: Optional[int] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict: Optional[dict] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pysqa_config_directory: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| backend: Optional[str] = None, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if resource_dict is None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict = {} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores_per_worker = resource_dict.get("cores", 1) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if "cwd" in resource_dict and resource_dict["cwd"] is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["cwd"] = os.path.abspath(resource_dict["cwd"]) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if cache_directory is not None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["cache_directory"] = os.path.abspath(cache_directory) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| else: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["cache_directory"] = os.path.abspath(".") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["hostname_localhost"] = hostname_localhost | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["log_obj_size"] = log_obj_size | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["pmi_mode"] = pmi_mode | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["init_function"] = init_function | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["config_directory"] = pysqa_config_directory | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| resource_dict["backend"] = backend | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_workers = validate_number_of_cores( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_cores=max_cores, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_workers=max_workers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cores_per_worker=cores_per_worker, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| set_local_cores=False, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return BlockAllocationTaskScheduler( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| max_workers=max_workers, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| executor_kwargs=resource_dict, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| spawner=PysqaSpawner, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Plumb cache_directory and worker_id into the spawner; don’t forward them to PySQA.
Ensures the worker dir logic can use these values and avoids leaking non-PySQA keys to
submit_job.class PysqaSpawner(BaseSpawner): def __init__( self, cwd: Optional[str] = None, cores: int = 1, threads_per_core: int = 1, gpus_per_core: int = 0, num_nodes: Optional[int] = None, exclusive: bool = False, openmpi_oversubscribe: bool = False, slurm_cmd_args: Optional[list[str]] = None, pmi_mode: Optional[str] = None, config_directory: Optional[str] = None, backend: Optional[str] = None, + cache_directory: Optional[str] = None, **kwargs, ): @@ - self._pysqa_submission_kwargs = kwargs + # Internal/non-PySQA fields + self._worker_id = kwargs.pop("worker_id", None) + # Accept via explicit arg or kwargs for BC + self._cache_directory = cache_directory or kwargs.pop("cache_directory", None) + # Remaining kwargs are forwarded to PySQA submit_job + self._pysqa_submission_kwargs = kwargs📝 Committable suggestion
🤖 Prompt for AI Agents