Skip to content

Commit 188a942

Browse files
committed
basic functionality for modules
1 parent 428abea commit 188a942

7 files changed

Lines changed: 78 additions & 0 deletions

File tree

docs/user/gourd.toml.5.tex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
For example one account available on DelftBlue is "Education-EEMCS-MSc-CS".
140140
To get a list of available accounts on your cluster,
141141
you can use Slurm's \Prog{sacctmgr}~\Arg{show}~\Arg{account} command
142+
\item[\Opt{modules} = list of strings]
143+
Modules to load when running through Slurm using the "module" utility.
144+
These are loaded in sequential order.
145+
For example, to use R in the DelftBlue cluster, \texttt{["2024r1", "r/3.4.0"]}.
146+
By default, no modules are loaded.
142147
\item[\Opt{mail\_type} = string]
143148
Choose one of Slurm's options for sending emails when a run's status changes.
144149
Default is "NONE". Valid options are:

src/gourd/init/interactive.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use gourd_lib::bailc;
77
use gourd_lib::config::slurm::SlurmConfig;
88
use gourd_lib::config::Config;
99
use gourd_lib::constants::CMD_STYLE;
10+
use gourd_lib::constants::EMPTY_MODULES;
1011
use gourd_lib::constants::WRAPPER_DEFAULT;
1112
use gourd_lib::ctx;
1213
use gourd_lib::file_system::FileOperations;
@@ -103,6 +104,7 @@ pub fn init_interactive(
103104
experiment_name: "my-experiment".to_string(),
104105
output_folder: PathBuf::from("./slurmout/"),
105106
partition: "".to_string(),
107+
modules: EMPTY_MODULES(),
106108
array_size_limit: None,
107109
max_submit: None,
108110
account: "".to_string(),

src/gourd/slurm/handler.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,17 @@ pub fn parse_optional_args(slurm_config: &SlurmConfig) -> String {
143143
result
144144
}
145145

146+
/// Helper function to create string with modules for slurm
147+
pub fn parse_modules(slurm_config: &SlurmConfig) -> String {
148+
let mut result = "".to_string();
149+
150+
for module in &slurm_config.modules {
151+
result.push_str(&format!("module load {}\n", module))
152+
}
153+
154+
result
155+
}
156+
146157
#[cfg(test)]
147158
#[path = "tests/handler.rs"]
148159
mod tests;

src/gourd/slurm/interactor.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use log::debug;
2121
use log::info;
2222
use log::trace;
2323

24+
use super::handler::parse_modules;
2425
use super::handler::parse_optional_args;
2526
use super::SacctOutput;
2627
use crate::chunks::Chunk;
@@ -215,6 +216,7 @@ impl SlurmInteractor for SlurmCli {
215216
let chunk_index = experiment.register_runs(&chunk.runs);
216217

217218
let optional_args = parse_optional_args(slurm_config);
219+
let modules = parse_modules(slurm_config);
218220

219221
// `%A` gets replaced with array *job* id, `%a` with the array *task* id
220222
// this is read in `src/gourd/status/slurm_files.rs` to get the output.
@@ -239,6 +241,7 @@ impl SlurmInteractor for SlurmCli {
239241
#SBATCH --error={:?}
240242
{}
241243
set -x
244+
{}
242245
243246
{} {} {} $SLURM_ARRAY_TASK_ID
244247
",
@@ -253,6 +256,7 @@ set -x
253256
slurm_out,
254257
slurm_err,
255258
optional_args,
259+
modules,
256260
experiment.wrapper,
257261
exp_path.display(),
258262
chunk_index

src/gourd/slurm/tests/handler.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ fn parse_optional_args_test_all() {
1111
experiment_name: "test experiment".to_string(),
1212
output_folder: Default::default(),
1313
partition: "memory".to_string(),
14+
modules: Default::default(),
1415
array_size_limit: None,
1516
max_submit: None,
1617
account: "test-account".to_string(),
@@ -34,6 +35,7 @@ fn parse_optional_args_test_only_begin() {
3435
experiment_name: "test experiment".to_string(),
3536
output_folder: Default::default(),
3637
partition: "memory".to_string(),
38+
modules: Default::default(),
3739
array_size_limit: None,
3840
max_submit: None,
3941
account: "test-account".to_string(),
@@ -69,6 +71,7 @@ fn parse_optional_args_test_custom_args() {
6971
experiment_name: "test experiment".to_string(),
7072
output_folder: Default::default(),
7173
partition: "memory".to_string(),
74+
modules: Default::default(),
7275
array_size_limit: None,
7376
max_submit: None,
7477
account: "test-account".to_string(),
@@ -86,3 +89,47 @@ fn parse_optional_args_test_custom_args() {
8689

8790
assert_eq!(output, desired_output)
8891
}
92+
93+
#[test]
94+
fn parse_modules_test_empty() {
95+
let config = SlurmConfig {
96+
experiment_name: "test experiment".to_string(),
97+
output_folder: Default::default(),
98+
partition: "memory".to_string(),
99+
modules: Vec::new(),
100+
array_size_limit: None,
101+
max_submit: None,
102+
account: "test-account".to_string(),
103+
begin: None,
104+
mail_type: Some("ALL".to_string()),
105+
mail_user: Some("testUSER".to_string()),
106+
additional_args: None,
107+
};
108+
let output = parse_modules(&config);
109+
let desired_output = "";
110+
111+
assert_eq!(output, desired_output)
112+
}
113+
114+
#[test]
115+
fn parse_modules_test_not_empty() {
116+
let config = SlurmConfig {
117+
experiment_name: "test experiment".to_string(),
118+
output_folder: Default::default(),
119+
partition: "memory".to_string(),
120+
modules: vec!["2024r1".to_string(), "r/3.4.0".to_string()],
121+
array_size_limit: None,
122+
max_submit: None,
123+
account: "test-account".to_string(),
124+
begin: None,
125+
mail_type: Some("ALL".to_string()),
126+
mail_user: Some("testUSER".to_string()),
127+
additional_args: None,
128+
};
129+
let output = parse_modules(&config);
130+
let desired_output = "module load 2024r1
131+
module load r/3.4.0
132+
";
133+
134+
assert_eq!(output, desired_output)
135+
}

src/gourd_lib/config/slurm.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use std::time::Duration;
66
use serde::Deserialize;
77
use serde::Serialize;
88

9+
use crate::constants::EMPTY_MODULES;
10+
911
/// The config options when running through Slurm
1012
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
1113
#[serde(deny_unknown_fields)]
@@ -27,6 +29,10 @@ pub struct SlurmConfig {
2729
/// - "visual"
2830
pub partition: String,
2931

32+
/// Which modules to load using the 'modules' command
33+
#[serde(default = "EMPTY_MODULES")]
34+
pub modules: Vec<String>,
35+
3036
/// Override the maximum number of jobs to schedule in a Slurm array.
3137
///
3238
/// If left `None`, a value fetched directly from slurm will be used.

src/gourd_lib/constants.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ pub const LABEL_OVERLAP_DEFAULT: fn() -> bool = || false;
3636
/// The default arguments for an input.
3737
pub const EMPTY_ARGS: fn() -> Vec<String> = Vec::new;
3838

39+
/// The default modules for a Slurm job.
40+
pub const EMPTY_MODULES: fn() -> Vec<String> = Vec::new;
41+
3942
/// The prefix which will cause an argument to be interpreted as a glob.
4043
/// Ensure matches:
4144
/// - docs/user/gourd.toml.5

0 commit comments

Comments
 (0)