This repository demonstrates how to run time series benchmarking experiments using sktime on a Slurm-managed compute cluster. sktime provides a benchmarking framework that lets you define an experiment declaratively and execute it on anything from a laptop to an HPC cluster.
Two files drive the whole experiment:
| File | Role |
|---|---|
benchmark.slurm |
Slurm batch script. This is what you submit. It sets up the Python environment on the compute node and then runs the benchmark. |
run_benchmark.py |
The benchmark itself. A short Python vignette that builds and runs a ForecastingBenchmark. |
When you submit the job with sbatch benchmark.slurm, Slurm schedules the batch script on a compute node. That script creates/activates a virtual environment, installs dependencies, and finally executes:
python run_benchmark.pySo: Slurm runs the .slurm file; the .slurm file runs the .py file.
The Python script does not know about Slurm, the same run_benchmark.py can be run locally with python run_benchmark.py.
Supporting files:
pyproject.toml: project dependencies (resolved withuv)logs/: Slurm stdout/stderr (output.log,error.log)M4_competition_yearly_results.csv: results written by the benchmark
- Running a forecasting benchmark on a Slurm cluster
- Using
ForecastingBenchmark - Using a reusable catalogue (
M4CompetitionCatalogueYearly) - Producing a results CSV
- Automatically setting up the Python environment on the compute node
-
Access to a Slurm cluster: a machine (or set of machines) where
sbatch,squeue, and related Slurm commands are available. Ask your HPC/admin team for an account if you do not already have one. Please refer to Slurm documentation for further information: https://slurm.schedmd.com/quickstart_admin.html -
A compute environment with:
- Python 3.11+ available (or installable)
uvavailable on the PATH (used bybenchmark.slurmto create the venv and install dependencies)- Network access from the compute node to install packages (PyPI and, for this demo, GitHub, see
pyproject.toml)
-
This repository checked out on a filesystem visible to both the login node and the compute nodes of the cluster.
Before submitting, edit the #SBATCH directives in benchmark.slurm to match your site:
--partition=main: change to a partition you are allowed to use--mem=8G: adjust memory for your estimators/datasets- Optionally add
--time=...,--cpus-per-task=...,--account=..., etc.
On a machine with the same Python/uv setup, you can validate the vignette without Slurm, though if the experiment is too large, it is not feasible:
uv venv --python 3.11
source .venv/bin/activate
uv sync
python run_benchmark.py From the repository root on the login node:
sbatch benchmark.slurmThe batch script will automatically:
- Create a
.venvif one does not already exist (uv venv --python 3.11) - Activate it
- Refresh/install dependencies (
uv lock,uv sync) - Run
python run_benchmark.py - Write stdout/stderr to
logs/output.logandlogs/error.log
squeue -u $USER
tail -f logs/output.log
# or
tail -f logs/error.logThe full experiment fits in a single short script. Follwing is the complete code alongwith explaination:
"""M4 competition yearly catalogue run on the slurm cluster."""
from sktime.benchmarking.forecasting import ForecastingBenchmark
from sktime.catalogues import M4CompetitionCatalogueYearly
from sktime.split import ExpandingWindowSplitter
catalogue = M4CompetitionCatalogueYearly()
benchmark = ForecastingBenchmark(backend="loky")
benchmark.add(catalogue)
benchmark.add(ExpandingWindowSplitter(initial_window=12, step_length=2, fh=6))
print(benchmark.estimators.entities)
print(benchmark.tasks.entities)
results = benchmark.run("./M4_competition_yearly_results.csv")The sections below walk through this vignette line by line: what a benchmark is, how catalogues work, how the CV strategy is added, and how results are written.
A benchmark in sktime consists of:
- estimators
- datasets
- evaluation strategy
- metrics
A dataset together with an evaluation strategy and a metric forms a task. These components are assembled into a ForecastingBenchmark:
from sktime.benchmarking.forecasting import ForecastingBenchmark
benchmark = ForecastingBenchmark(backend="loky")Estimators and tasks are then added to that benchmark instance.
Components can be registered one by one:
add_estimator: add estimatorsadd_task: add tasksadd: convenience wrapper overadd_estimatorandadd_taskthat infers the scitype and registers the component
See the sktime example notebook: https://www.sktime.net/en/latest/examples/04_benchmarking_forecasters.html
Simply put, a catalogue is a collection of objects. It can also be used as reusable specification of a benchmarking experiment. Rather than manually registering every estimator, dataset, metric, and configuration, a catalogue bundles these into a single object that can be added directly to the benchmark. Catalogues may be partial, as in this example, where the CV splitter is left for the user to choose.
This demo uses M4CompetitionCatalogueYearly:
from sktime.catalogues import M4CompetitionCatalogueYearly
catalogue = M4CompetitionCatalogueYearly()
benchmark.add(catalogue)That registers the catalogue's components on the benchmark. M4CompetitionCatalogueYearly ships with sktime and currently includes the statistical baselines from the M4 competition, the M4 yearly dataset, and the competition metrics. You can define your own catalogues by inheriting from sktime's BaseCatalogue.
Docs: https://www.sktime.net/en/latest/api_reference/catalogues.html
The original M4 competition used fixed train/test files. In sktime, a task needs a CV strategy, so the vignette adds an expanding-window splitter. This could live in the catalogue, but because the original competition did not specify a splitter, it is left to the user:
from sktime.split import ExpandingWindowSplitter
benchmark.add(
ExpandingWindowSplitter(
initial_window=12,
step_length=2,
fh=6,
)
)results = benchmark.run("./M4_competition_yearly_results.csv")This evaluates every estimator on every task with the configured splitter and writes results to M4_competition_yearly_results.csv. JSON and Parquet are also supported. Result writing is crash-safe, i.e., if a run fails partway through in case of a system failure etc., re-running the experiment loads existing results and continues with the remaining experiments.
ForecastingBenchmark(backend="loky") controls how jobs are parallelized. sktime currently parallelizes across CV folds; different backends provide different parallelization strategies. For different backends we support and the general API, please checkout out docs.
- Adapt
run_benchmark.py(estimators, catalogues, splitters, output path) using the patterns above, you can either create a catalogue and then add it to the benchmark, or build your benchmark manually. - Update
pyproject.tomlwith any extra dependencies your estimators or dataset loaders need, you can find the dependencies from the tags. - Adjust the
#SBATCHresource requests inbenchmark.slurm(memory, time, CPUs, partition). - Submit with
sbatch benchmark.slurm.