Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions executorlib/interactive/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,8 @@ class FluxPythonSpawner(BaseSpawner):
cores (int, optional): The number of cores. Defaults to 1.
threads_per_core (int, optional): The number of threads per base. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per base. 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, optional): Whether to oversubscribe. Defaults to False.
flux_executor (flux.job.FluxExecutor, optional): The FluxExecutor instance. Defaults to None.
flux_executor_pmi_mode (str, optional): The PMI option. Defaults to None.
Expand All@@ -42,6 +44,8 @@ def __init__(
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,
flux_executor: Optional[flux.job.FluxExecutor] = None,
flux_executor_pmi_mode: Optional[str] = None,
Expand All@@ -55,6 +59,8 @@ def __init__(
)
self._threads_per_core = threads_per_core
self._gpus_per_core = gpus_per_core
self._num_nodes = num_nodes
self._exclusive = exclusive
self._flux_executor = flux_executor
self._flux_executor_pmi_mode = flux_executor_pmi_mode
self._flux_executor_nesting = flux_executor_nesting
Expand DownExpand Up@@ -85,17 +91,17 @@ def bootup(
num_tasks=self._cores,
cores_per_task=self._threads_per_core,
gpus_per_task=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
else:
jobspec = flux.job.JobspecV1.from_nest_command(
command=command_lst,
num_slots=self._cores,
cores_per_slot=self._threads_per_core,
gpus_per_slot=self._gpus_per_core,
num_nodes=None,
exclusive=False,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
)
jobspec.environment = dict(os.environ)
if self._flux_executor_pmi_mode is not None:
Expand Down
16 changes: 16 additions & 0 deletions executorlib/interactive/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -27,6 +27,8 @@ def __init__(
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,
):
Expand All@@ -38,6 +40,8 @@ def __init__(
cores (int, optional): The number of cores to use. Defaults to 1.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].
"""
Expand All@@ -49,6 +53,8 @@ def __init__(
)
self._gpus_per_core = gpus_per_core
self._slurm_cmd_args = slurm_cmd_args
self._num_nodes = num_nodes
self._exclusive = exclusive

def generate_command(self, command_lst: list[str]) -> list[str]:
"""
Expand All@@ -65,6 +71,8 @@ def generate_command(self, command_lst: list[str]) -> list[str]:
cwd=self._cwd,
threads_per_core=self._threads_per_core,
gpus_per_core=self._gpus_per_core,
num_nodes=self._num_nodes,
exclusive=self._exclusive,
openmpi_oversubscribe=self._openmpi_oversubscribe,
slurm_cmd_args=self._slurm_cmd_args,
)
Expand All@@ -78,6 +86,8 @@ def generate_slurm_command(
cwd: Optional[str],
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,
) -> list[str]:
Expand All@@ -89,6 +99,8 @@ def generate_slurm_command(
cwd (str): The current working directory.
threads_per_core (int, optional): The number of threads per core. Defaults to 1.
gpus_per_core (int, optional): The number of GPUs per core. 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, optional): Whether to oversubscribe the cores. Defaults to False.
slurm_cmd_args (list[str], optional): Additional command line arguments. Defaults to [].

Expand All@@ -98,10 +110,14 @@ def generate_slurm_command(
command_prepend_lst = [SLURM_COMMAND, "-n", str(cores)]
if cwd is not None:
command_prepend_lst += ["-D", cwd]
if num_nodes is not None:
command_prepend_lst += ["-N", str(num_nodes)]
if threads_per_core > 1:
command_prepend_lst += ["--cpus-per-task=" + str(threads_per_core)]
if gpus_per_core > 0:
command_prepend_lst += ["--gpus-per-task=" + str(gpus_per_core)]
if exclusive:
command_prepend_lst += ["--exact"]
if openmpi_oversubscribe:
command_prepend_lst += ["--oversubscribe"]
if slurm_cmd_args is not None and len(slurm_cmd_args) > 0:
Expand Down
23 changes: 12 additions & 11 deletions executorlib/interfaces/flux.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -43,9 +43,10 @@ class FluxJobExecutor:
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -147,10 +148,10 @@ def __new__(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand DownExpand Up@@ -444,10 +445,10 @@ def create_flux_executor(
- threads_per_core (int): number of OpenMP threads to be used for each function call
- gpus_per_core (int): number of GPUs per worker - defaults to 0
- cwd (str/None): current working directory where the parallel python task is executed
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
flux_executor (flux.job.FluxExecutor): Flux Python interface to submit the workers to flux
flux_executor_pmi_mode (str): PMI interface to use (OpenMPI v5 requires pmix) default is None (Flux only)
flux_executor_nesting (bool): Provide hierarchically nested Flux job scheduler inside the submitted function.
Expand Down
12 changes: 12 additions & 0 deletions executorlib/interfaces/slurm.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -227,6 +227,10 @@ class SlurmJobExecutor:
- openmpi_oversubscribe (bool): adds the `--oversubscribe` command line flag (OpenMPI and
SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -320,6 +324,10 @@ def __new__(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand DownExpand Up@@ -409,6 +417,10 @@ def create_slurm_executor(
and SLURM only) - default False
- slurm_cmd_args (list): Additional command line arguments for the srun call (SLURM
only)
- 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.
hostname_localhost (boolean): use localhost instead of the hostname to establish the zmq connection. In the
context of an HPC cluster this essential to be able to communicate to an
Executor running on a different compute node within the same allocation. And
Expand Down
6 changes: 4 additions & 2 deletions tests/test_pysqa_subprocess.py
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,9 +51,11 @@ def test_generate_slurm_command(self):
cwd="/tmp/test",
threads_per_core=2,
gpus_per_core=1,
num_nodes=1,
exclusive=True,
openmpi_oversubscribe=True,
slurm_cmd_args=["--help"],
)
self.assertEqual(len(command_lst), 9)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '--cpus-per-task=2', '--gpus-per-task=1', '--oversubscribe', '--help']
self.assertEqual(len(command_lst), 12)
reply_lst = ['srun', '-n', '1', '-D', '/tmp/test', '-N', '1', '--cpus-per-task=2', '--gpus-per-task=1', '--exact', '--oversubscribe', '--help']
self.assertEqual(command_lst, reply_lst)