Skip to content
23 changes: 22 additions & 1 deletion docs/further.md
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ To adapt the workflow for an application using `mpiexec`, you can override the `
``` console
$ snakemake --set-resources calc_pi:mpi="mpiexec" ...
```

##### Resource Specifications for MPI Jobs

When configuring MPI jobs, it's essential to accurately define the resources to match the requirements of your application.
Expand Down Expand Up @@ -518,6 +517,28 @@ In this configuration:

By defining these resource specifications in a profile, you maintain a clean and organized workflow, ensuring that resource allocations are consistent and easily adjustable.

### Setting tmpspace with GRES
On certain clusters the amount of scratch/tmpspace on the worker node can be set with:
`--gres=tmpspace:10G`

*this depends on the cluser config and is not a default*

You can specify the amount of tmpspace using the `gres` resource:

```Python
rule tmpspace_task:
input:
"input_file"
output:
"output_file"
resources:
gres="tmpspace:15G"
shell:
"tmpspace_task --input {input} --output {output}"
```



### Running Jobs locally

In Snakemake workflows executed within cluster environments, certain tasks -- such as brief data downloads or plotting -- are better suited for local execution on the head node rather than being submitted as cluster jobs.
Expand Down
35 changes: 21 additions & 14 deletions snakemake_executor_plugin_slurm/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,10 @@ def set_gres_string(job: JobExecutorInterface) -> str:
# generic resources (GRES) arguments can be of type
# "string:int" or "string:string:int"
gres_re = re.compile(r"^[a-zA-Z0-9_]+(:[a-zA-Z0-9_\.]+)?:\d+$")

# generic resources (GRES) arguments can be of type
# "string:int[TGM]" when a tmpspace is specified.
gres_tmpspace_re = re.compile(r"^tmpspace:\d+[TGM]?$")
# gpu model arguments can be of type "string"
# The model string may contain a dot for variants, see
# https://github.com/snakemake/snakemake-executor-plugin-slurm/issues/387
Expand Down Expand Up @@ -283,20 +287,23 @@ def set_gres_string(job: JobExecutorInterface) -> str:
# Validate GRES format (e.g., "gpu:1", "gpu:tesla:2")
gres = job.resources.gres
if not gres_re.match(gres):
if not string_check.match(gres):
raise WorkflowError(
"GRES format should not be a nested string (start "
"and end with ticks or quotation marks). "
"Expected format: "
"'<name>:<number>' or '<name>:<type>:<number>' "
"(e.g., 'gpu:1' or 'gpu:tesla:2')"
)
else:
raise WorkflowError(
f"Invalid GRES format: {gres}. Expected format: "
"'<name>:<number>' or '<name>:<type>:<number>' "
"(e.g., 'gpu:1' or 'gpu:tesla:2')"
)
if not gres_tmpspace_re.match(gres):
if not string_check.match(gres):
raise WorkflowError(
"GRES format should not be a nested string (start "
"and end with ticks or quotation marks). "
"Expected format: "
"'<name>:<number>' or '<name>:<type>:<number>' or "
"'tmpspace:<number>[TGM]' "
"(e.g., 'gpu:1' or 'gpu:tesla:2') or tmpspace:10G "
)
else:
raise WorkflowError(
f"Invalid GRES format: {gres}. Expected format: "
"'<name>:<number>' or '<name>:<type>:<number>' "
"or 'tmpspace:<number>[TGM]' "
"(e.g., 'gpu:1' or 'gpu:tesla:2') or tmpspace:10G "
)
return f" --gres={job.resources.gres}"

if gpu_model and gpu_string:
Expand Down
14 changes: 14 additions & 0 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,20 @@ def test_gpu_model_without_gpu(self, mock_job):
):
set_gres_string(job)

def test_tmpspace_gres_10G(self, mock_job):
"""Test with valid GRES format (simple)."""
job = mock_job(gres="tmpspace:10G")

# Patch subprocess.Popen to capture the sbatch command
with patch("subprocess.Popen") as mock_popen:
# Configure the mock to return successful submission
process_mock = MagicMock()
process_mock.communicate.return_value = ("123", "")
process_mock.returncode = 0
mock_popen.return_value = process_mock

assert set_gres_string(job) == " --gres=tmpspace:10G"

def test_both_gres_and_gpu_set(self, mock_job):
"""Test error case when both GRES and GPU are specified."""
job = mock_job(gres="gpu:1", gpu="2")
Expand Down
Loading