22
33> ** TL;DR**
44> * Sync* : return a scalar or a dict ⟶ NePS records it automatically.
5- > * Async* : return ` None ` , launch a job, and call ` neps.save_callback () ` when the job finishes.
5+ > * Async* : return ` None ` , launch a job, and call ` neps.save_pipeline_results () ` when the job finishes.
66
77---
88
@@ -57,7 +57,6 @@ All other values raise a `TypeError` inside NePS.
5757
5858``` python
5959from pathlib import Path
60- import subprocess
6160import neps
6261
6362def evaluate_pipeline (
@@ -67,9 +66,8 @@ def evaluate_pipeline(
6766 learning_rate : float ,
6867 optimizer : str ,
6968):
70- # 1) write a Slurm script into the trial dir
71- sh = pipeline_directory / " run.sh"
72- sh.write_text(f """ #!/bin/bash
69+ # 1) write a Slurm script
70+ script = f """ #!/bin/bash
7371#SBATCH --time=0-00:10
7472#SBATCH --job-name=trial_ { pipeline_id}
7573#SBATCH --partition=bosch_cpu-cascadelake
@@ -82,10 +80,9 @@ python run_pipeline.py \
8280 --pipeline_id { pipeline_id} \
8381 --root_dir { root_directory}
8482""" )
85- sh.chmod(0o 755 )
8683
8784 # 2) submit and RETURN None (async)
88- subprocess.check_call([ " sbatch " , str (sh)] )
85+ sumit_job(script )
8986 return None # ⟵ signals async mode
9087```
9188
@@ -101,17 +98,22 @@ parser.add_argument("--optimizer")
10198parser.add_argument(" --pipeline_id" )
10299parser.add_argument(" --root_dir" )
103100args = parser.parse_args()
104-
105- # … do heavy training …
106- val_loss = 0.1234
107- wall_clock_cost = 180 # seconds
108-
109- result = {
110- " objective_to_minimize" : val_loss,
111- " cost" : wall_clock_cost,
112- }
113-
114- neps.save_callback(
101+ try :
102+ # … do heavy training …
103+ val_loss = 0.1234
104+ wall_clock_cost = 180 # seconds
105+ result = {
106+ " objective_to_minimize" : val_loss,
107+ " cost" : wall_clock_cost,
108+ }
109+ except Exception as e:
110+ result = {
111+ " objective_to_minimize" : val_loss,
112+ " cost" : wall_clock_cost,
113+ " exception" : e
114+ }
115+
116+ neps.save_pipeline_results(
115117 user_result = result,
116118 pipeline_id = args.pipeline_id,
117119 root_directory = Path(args.root_dir),
@@ -131,9 +133,8 @@ neps.save_callback(
131133| name | provided when | description |
132134| ----------------------------- | ----------------------- | ---------------------------------------------------------- |
133135| ` pipeline_directory ` | always | per‑trial working dir (` …/trials/<id>/ ` ) |
134- | ` previous_pipeline_directory ` | only for multi‑fidelity | directory of the lower‑fidelity checkpoint. Can be ` None ` . |
135- | ` pipeline_id ` | async only | trial id string you pass to ` save_evaluation_results ` |
136- | ` root_directory ` | async only | optimisation root folder, same to pass back |
136+ | ` previous_pipeline_directory ` | always | directory of the lower‑fidelity checkpoint. Can be ` None ` . |
137+ | ` pipeline_id ` | always | trial id string you pass to ` save_evaluation_results ` |
137138
138139Use them to handle warm‑starts, logging and result persistence.
139140
@@ -143,6 +144,6 @@ Use them to handle warm‑starts, logging and result persistence.
143144
144145* [x] Return scalar ** or** dict ** or** ` None ` .
145146* [x] Include ` cost ` when using cost budgets.
146- * [x] When returning ` None ` , make sure ** exactly one** call to ` neps.save_callback ` happens.
147+ * [x] When returning ` None ` , make sure ** exactly one** call to ` neps.save_pipeline_results ` happens.
147148* [x] Save checkpoints and artefacts in ` pipeline_directory ` .
148149* [x] Handle resume via ` previous_pipeline_directory ` .
0 commit comments