Skip to content

Commit 391eb6b

Browse files
authored
Merge pull request #439 from ExaWorks/pbs_fixes
Added resource specs to PBS executor, which were somehow missing.
2 parents 991a6a0 + 5706789 commit 391eb6b

File tree

8 files changed

+159
-21
lines changed

8 files changed

+159
-21
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from distutils.version import StrictVersion
2+
3+
from psij.descriptor import Descriptor
4+
5+
6+
__PSI_J_EXECUTORS__ = [Descriptor(name='pbs', nice_name='PBS Pro', aliases=['pbspro'],
7+
version=StrictVersion('0.0.2'),
8+
cls='psij.executors.batch.pbs.PBSJobExecutor'),
9+
Descriptor(name='pbs_classic', nice_name='PBS Classic', aliases=['torque'],
10+
version=StrictVersion('0.0.2'),
11+
cls='psij.executors.batch.pbs_classic.PBSClassicJobExecutor')]

src/psij-descriptors/pbspro_descriptor.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

src/psij/executors/batch/pbs.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from pathlib import Path
2+
from typing import Optional
3+
4+
from psij.executors.batch.pbs_base import PBSExecutorConfig, GenericPBSJobExecutor
5+
from psij.executors.batch.script_generator import TemplatedScriptGenerator
6+
7+
8+
class PBSJobExecutor(GenericPBSJobExecutor):
9+
"""A :class:`~psij.JobExecutor` for PBS Pro and friends.
10+
11+
This executor uses resource specifications specific to PBS Pro
12+
"""
13+
14+
def __init__(self, url: Optional[str] = None, config: Optional[PBSExecutorConfig] = None):
15+
"""
16+
Parameters
17+
----------
18+
url
19+
Not used, but required by the spec for automatic initialization.
20+
config
21+
An optional configuration for this executor.
22+
"""
23+
if not config:
24+
config = PBSExecutorConfig()
25+
generator = TemplatedScriptGenerator(config, Path(__file__).parent / 'pbspro'
26+
/ 'pbspro.mustache')
27+
super().__init__(generator, url=url, config=config)
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#!/bin/bash
2+
3+
4+
{{#job.name}}
5+
#PBS -N="{{.}}"
6+
{{/job.name}}
7+
8+
{{#job.spec.inherit_environment}}
9+
#PBS -V
10+
{{/job.spec.inherit_environment}}
11+
12+
{{#job.spec.resources}}
13+
{{#process_count}}
14+
#PBS -l nodes={{job.spec.resources.computed_node_count}}:ppn={{.}}{{#job.spec.resources.gpu_cores_per_process}}:gpus={{.}}{{/job.spec.resources.gpu_cores_per_process}}
15+
{{/process_count}}
16+
{{#exclusive_node_use}}
17+
#PBS -n
18+
{{/exclusive_node_use}}
19+
{{/job.spec.resources}}
20+
21+
{{#formatted_job_duration}}
22+
#PBS -l walltime={{.}}
23+
{{/formatted_job_duration}}
24+
25+
{{#job.spec.attributes}}
26+
{{#project_name}}
27+
#PBS -P {{.}}
28+
{{/project_name}}
29+
{{#queue_name}}
30+
#PBS -q {{.}}
31+
{{/queue_name}}
32+
{{!PBS uses specially named queues for reservations, so we send the job to the respective
33+
queue when a reservation ID is specified.}}
34+
{{#reservation_id}}
35+
#PBS -q {{.}}
36+
{{/reservation_id}}
37+
{{/job.spec.attributes}}
38+
39+
{{#custom_attributes}}
40+
{{#pbs}}
41+
#PBS -{{key}} "{{value}}"
42+
{{/pbs}}
43+
{{/custom_attributes}}
44+
45+
46+
{{!since we redirect the output manually, below, tell pbs not to do its own thing, since it
47+
only results in empty files that are not cleaned up}}
48+
#PBS -e /dev/null
49+
#PBS -o /dev/null
50+
51+
{{#job.spec.inherit_environment}}
52+
#PBS -V
53+
{{/job.spec.inherit_environment}}
54+
{{#env}}
55+
#PBS -v {{name}}={{value}}
56+
{{/env}}
57+
58+
PSIJ_NODEFILE="$PBS_NODEFILE"
59+
export PSIJ_NODEFILE
60+
61+
62+
{{#job.spec.directory}}
63+
cd "{{.}}"
64+
{{/job.spec.directory}}
65+
66+
exec &>> "{{psij.script_dir}}/$PBS_JOBID.out"
67+
68+
{{#psij.launch_command}}{{.}} {{/psij.launch_command}}
69+
70+
{{!we redirect to a file tied to the native ID so that we can reach the file with attach().}}
71+
echo "$?" > "{{psij.script_dir}}/$PBS_JOBID.ec"

src/psij/executors/batch/pbspro/pbspro.mustache renamed to src/psij/executors/batch/pbs/pbspro.mustache

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
#!/bin/bash
22

3-
# TODO: job.spec.resources
4-
# TODO: job.spec.attributes
53

64
{{#job.name}}
75
#PBS -N="{{.}}"
@@ -11,6 +9,18 @@
119
#PBS -V
1210
{{/job.spec.inherit_environment}}
1311

12+
{{#job.spec.resources}}
13+
{{#process_count}}
14+
#PBS -l select={{job.spec.resources.computed_node_count}}:ncpus={{.}}
15+
{{/process_count}}
16+
{{#exclusive_node_use}}
17+
#PBS -l place=scatter:exclhost
18+
{{/exclusive_node_use}}
19+
{{^exclusive_node_use}}
20+
#PBS -l place=scatter:shared
21+
{{/exclusive_node_use}}
22+
{{/job.spec.resources}}
23+
1424
{{#formatted_job_duration}}
1525
#PBS -l walltime={{.}}
1626
{{/formatted_job_duration}}
Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
_QSTAT_COMMAND = 'qstat'
1313

14-
# This table maps PBS Pro state codes to the corresponding PSI/J
14+
# This table maps PBS state codes to the corresponding PSI/J
1515
# JobState.
1616
# See https://www.altair.com/pdfs/pbsworks/PBSReferenceGuide2021.1.pdf
1717
# page 361, section 8.1 "Job States"
@@ -39,14 +39,14 @@
3939
}
4040

4141

42-
class PBSProExecutorConfig(BatchSchedulerExecutorConfig):
43-
"""A configuration class for the PBS executor."""
42+
class PBSExecutorConfig(BatchSchedulerExecutorConfig):
43+
"""A generic configuration class for PBS-type executors."""
4444

4545
pass
4646

4747

48-
class PBSProJobExecutor(BatchSchedulerExecutor):
49-
"""A :class:`~psij.JobExecutor` for PBS.
48+
class GenericPBSJobExecutor(BatchSchedulerExecutor):
49+
"""A generic :class:`~psij.JobExecutor` for PBS-type schedulers.
5050
5151
PBS, originally developed by NASA, is one of the oldest resource managers still in use.
5252
A number of variations are available: `PBS Pro <https://www.altair.com/pbs-professional/>`_,
@@ -60,7 +60,8 @@ class PBSProJobExecutor(BatchSchedulerExecutor):
6060
Creates a batch script with #PBS directives when submitting a job.
6161
"""
6262

63-
def __init__(self, url: Optional[str] = None, config: Optional[PBSProExecutorConfig] = None):
63+
def __init__(self, generator: TemplatedScriptGenerator, url: Optional[str] = None,
64+
config: Optional[PBSExecutorConfig] = None) -> None:
6465
"""
6566
Parameters
6667
----------
@@ -69,11 +70,8 @@ def __init__(self, url: Optional[str] = None, config: Optional[PBSProExecutorCon
6970
config
7071
An optional configuration for this executor.
7172
"""
72-
if not config:
73-
config = PBSProExecutorConfig()
7473
super().__init__(url=url, config=config)
75-
self.generator = TemplatedScriptGenerator(config, Path(__file__).parent / 'pbspro'
76-
/ 'pbspro.mustache')
74+
self.generator = generator
7775

7876
# Submit methods
7977

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from pathlib import Path
2+
from typing import Optional
3+
4+
from psij.executors.batch.pbs_base import PBSExecutorConfig, GenericPBSJobExecutor
5+
from psij.executors.batch.script_generator import TemplatedScriptGenerator
6+
7+
8+
class PBSClassicJobExecutor(GenericPBSJobExecutor):
9+
"""A :class:`~psij.JobExecutor` for classic PBS systems.
10+
11+
This executor uses resource specifications specific to Open PBS. Specifically,
12+
this executor uses the `-l nodes=n:ppn=m` way of specifying nodes, which
13+
differs from the scheme used by PBS Pro.
14+
"""
15+
16+
def __init__(self, url: Optional[str] = None, config: Optional[PBSExecutorConfig] = None):
17+
"""
18+
Parameters
19+
----------
20+
url
21+
Not used, but required by the spec for automatic initialization.
22+
config
23+
An optional configuration for this executor.
24+
"""
25+
if not config:
26+
config = PBSExecutorConfig()
27+
generator = TemplatedScriptGenerator(config, Path(__file__).parent / 'pbs'
28+
/ 'pbs_classic.mustache')
29+
super().__init__(generator, url=url, config=config)

tests/test_executor.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def _check_str_attrs(ex: BatchSchedulerExecutor, job: Job, names: List[str],
194194
pytest.fail('Script generation failed for %s' % name)
195195

196196

197-
_PREFIX_TR = {'pbspro': 'pbs'}
197+
_PREFIX_TR = {'pbspro': 'pbs', 'pbs_classic': 'pbs'}
198198

199199

200200
def _get_attr_prefix(exec_name: str) -> str:

0 commit comments

Comments
 (0)