API Reference
Everything here is importable from the top-level package, e.g.
from dask_setup import setup_dask_client. Helpers backed by optional
dependencies (xarray, dask-jobqueue, zarr) raise an ImportError naming the
install command when the dependency is missing.
Cluster setup
- dask_setup.client.setup_dask_client(workload_type: str | None = None, max_workers: int | None = None, reserve_mem_gb: float | None = None, max_mem_gb: float | None = None, dashboard: bool | None = None, adaptive: bool | None = None, min_workers: int | None = None, profile: str | None = None, suggest_chunks: bool | None = None, config: DaskSetupConfig | None = None, ds: None = None, fallback_on_detection_failure: bool = False, adaptive_memory: bool = False, mode: str = 'interactive', multi_node_config: MultiNodeConfig | None = None) tuple[Client, LocalCluster, str][source]
- dask_setup.client.setup_dask_client(workload_type: str | None = None, max_workers: int | None = None, reserve_mem_gb: float | None = None, max_mem_gb: float | None = None, dashboard: bool | None = None, adaptive: bool | None = None, min_workers: int | None = None, profile: str | None = None, suggest_chunks: bool | None = None, config: DaskSetupConfig | None = None, ds: xr.Dataset | xr.DataArray = None, fallback_on_detection_failure: bool = False, adaptive_memory: bool = False, mode: str = 'interactive', multi_node_config: MultiNodeConfig | None = None) tuple[Client, LocalCluster, str, dict[str, int]]
Create a single-node Dask LocalCluster tuned for HPC login/compute nodes.
Routes temp/spill to
$PBS_JOBFSwhen present.Every configuration parameter below defaults to
None, meaning “not supplied”. Values are resolved in this order, highest priority first:Parameters you pass explicitly here
profile=config=DaskSetupConfigfield defaults
A parameter you leave at
Nonekeeps whatever the profile or config object specifies; a parameter you pass always wins, even when the value happens to equal the library default.- Parameters:
workload_type ({"cpu","io","mixed","gpu","auto"} or None) – Shape worker topology for CPU-bound, I/O-bound, or mixed workloads.
Noneinherits from the profile/config, falling back to"io".max_workers (int or None) – Cap on worker processes. Defaults to all logical cores available.
reserve_mem_gb (float or None) – Memory to reserve for OS / cache / filesystem (GiB).
Noneinherits from the profile/config, falling back to a machine-aware default: 20% of total RAM, clamped to [4.0, 50.0] GiB.max_mem_gb (float or None) – Cap total memory used by Dask. Default is node total.
dashboard (bool or None) – If True, start a dashboard on a random free port and print an SSH tunnel hint.
Noneinherits, falling back to True.adaptive (bool or None) – Enable single-node adaptive scaling (elastic number of workers).
Noneinherits, falling back to False.min_workers (int or None) – Minimum workers when adaptive=True.
profile (str or None) – Name of configuration profile to use. Profile settings override
config=and are in turn overridden by explicit parameters. Pass"auto"to select a profile from the detected resources.suggest_chunks (bool) – If True, print xarray chunking recommendations after cluster setup. When
ds=is also provided, the recommendations are computed from the actual dataset. Withoutds=, generic guidance is printed. Requires xarray and numpy to be installed.config (DaskSetupConfig or None) –
A pre-built configuration object supplying every field at once. This is the recommended way to avoid the default-value ambiguity that occurs with individual keyword parameters.
The full precedence, lowest to highest, is:
library defaults < config= or profile= < explicit keywords
config=andprofile=occupy the same layer rather than stacking: passing both is allowed, but the profile supplies the base and the config object is ignored. Use explicit keyword arguments for anything you want on top.ds (xr.Dataset, xr.DataArray, or None) –
Optional xarray dataset. When provided:
Chunk validation is run automatically (warnings emitted for dangerously large or very small existing chunks).
Chunk recommendations are computed for the specific dataset and cluster configuration, and returned as the fourth element of the return tuple.
If
suggest_chunks=True, the recommendations are also printed.
Requires xarray and numpy to be installed.
fallback_on_detection_failure (bool) – If
True, use conservative hardcoded defaults (2 cores, 8 GiB) when all resource detection methods fail, instead of raisingResourceDetectionError. A warning is logged. DefaultFalsepreserves the existing behaviour of raising on failure.adaptive_memory (bool) – If
True, calltune_memory_thresholds()once after the cluster is ready. This reads the (initially zero) spill stats and tightens the workermemory.target/memory.spillthresholds slightly, giving workers more head-room from the start. DefaultFalse.mode ({"interactive", "auto", "local", "pbs", "slurm"}) –
Backend selection.
"interactive"(default) — use resources already allocated in the current PBS or SLURM job, interactive (qsub -I,salloc) or batch. Never submits new jobs. Multi-node allocations create anSSHClusteracross all nodes inPBS_NODEFILE/SLURM_NODELIST; a single node, or no allocation at all, gets the sameLocalClusteras"local"."local"— always use a single-nodeLocalCluster(default behaviour prior to v2.0)."pbs"— launch viadask-jobqueue.PBSCluster(submits new batch jobs). Requirespip install dask-jobqueue."slurm"— launch viadask-jobqueue.SLURMCluster(submits new batch jobs)."auto"— inspect the environment and choose"interactive"when inside a PBS interactive job (PBS_ENVIRONMENT=PBS_INTERACTIVE) or a SLURM interactive allocation (SLURM_BATCH_FLAGnot set to"1");"pbs"whenPBS_JOBIDis set in a batch job;"slurm"whenSLURM_JOB_IDis set in a batch job;"local"otherwise.
multi_node_config (MultiNodeConfig or None) – Configuration for the multi-node backend (
mode="pbs"or"slurm"). Ignored whenmode="local". WhenNoneand a multi-node mode is selected, a defaultMultiNodeConfigis constructed from workload_type.
- Returns:
When
dsisNone(default) –(client, cluster, dask_local_dir)— a 3-tuple.When
dsis provided –(client, cluster, dask_local_dir, chunks)— a 4-tuple, where chunks is adict[str, int]of recommended chunk sizes for that dataset (can be passed directly tods.chunk(chunks)).
- Raises:
InvalidConfigurationError – If workload_type is invalid or parameters are inconsistent.
InsufficientResourcesError – If system resources are insufficient for the requested configuration.
ResourceDetectionError – If resource detection fails completely.
- Return type:
tuple[Client, LocalCluster, str] | tuple[Client, LocalCluster, str, dict[str, int]]
See also
DaskClientContextContext manager version that closes the cluster on exit.
validate_chunksValidate existing chunking against cluster memory limits.
recommend_chunksStandalone chunk recommendation function.
rechunk_datasetRechunk a dataset to new target chunk sizes.
Examples
# Basic usage (3-tuple) client, cluster, tmp = setup_dask_client(workload_type="io") # Basic usage (3-tuple) client, cluster, tmp = setup_dask_client(workload_type="io") # With dataset — chunk validation + recommendations (4-tuple) ds = xr.open_zarr("era5.zarr") client, cluster, tmp, chunks = setup_dask_client(ds=ds, suggest_chunks=True) ds_opt = ds.chunk(chunks) # Multi-node PBS — submits worker jobs via dask-jobqueue client, cluster, tmp = setup_dask_client( mode="pbs", multi_node_config=MultiNodeConfig( workers_per_node=4, cores_per_worker=12, mem_per_worker_gb=32.0, walltime="04:00:00", ), )
- class dask_setup.client.DaskClientContext(**kwargs)[source]
Bases:
objectContext manager wrapper for
setup_dask_client().Ensures the Dask client and cluster are closed cleanly on exit — even when an exception is raised inside the
withblock.All keyword arguments accepted by
setup_dask_client()are valid.When a dataset is passed via
ds=, the context manager yields a 4-tuple(client, cluster, tmp, chunks)where chunks is the recommended chunk dictionary for that dataset. Withoutds=, the familiar 3-tuple(client, cluster, tmp)is yielded.Examples
from dask_setup import DaskClientContext # 3-tuple form (no dataset) with DaskClientContext(workload_type="cpu") as (client, cluster, tmp): result = client.compute(ds.mean()) # 4-tuple form (with dataset — chunks auto-computed) with DaskClientContext(ds=my_ds, suggest_chunks=True) as (client, cluster, tmp, chunks): ds_opt = my_ds.chunk(chunks) result = client.compute(ds_opt.mean())
The context manager does not delete the spill/temp directory on exit so that users can inspect spill artefacts for debugging if needed.
- Parameters:
kwargs (Any)
Configuration and profiles
- class dask_setup.config.DaskSetupConfig(workload_type='io', max_workers=None, reserve_mem_gb=50.0, max_mem_gb=None, dashboard=True, adaptive=False, min_workers=None, temp_base_dir=None, dashboard_port=None, silence_logs=False, memory_target=0.75, memory_spill=0.85, memory_pause=0.92, memory_terminate=0.98, spill_compression='auto', comm_compression=False, spill_threads=None, suggest_chunks=False, io_format=None, io_target_chunk_mb=(128, 512), io_access_pattern='auto', io_storage_location='auto', io_compression_level=None, fallback_on_detection_failure=False, adaptive_memory=False, name='', description='', tags=<factory>)[source]
Bases:
objectConfiguration for dask_setup with validation and defaults.
This class encapsulates all configuration parameters for setup_dask_client(), provides validation, and supports serialization for profile management.
- Parameters:
workload_type (str)
max_workers (int | None)
reserve_mem_gb (float)
max_mem_gb (float | None)
dashboard (bool)
adaptive (bool)
min_workers (int | None)
temp_base_dir (str | None)
dashboard_port (int | None)
silence_logs (bool)
memory_target (float)
memory_spill (float)
memory_pause (float)
memory_terminate (float)
spill_compression (str)
comm_compression (bool)
spill_threads (int | None)
suggest_chunks (bool)
io_format (str | None)
io_access_pattern (str)
io_storage_location (str)
io_compression_level (int | None)
fallback_on_detection_failure (bool)
adaptive_memory (bool)
name (str)
description (str)
- validate()[source]
Validate all configuration parameters.
- Raises:
ConfigurationValidationError – If any parameter is invalid
- Return type:
None
- classmethod from_dict(data, skip_validation=False)[source]
Create configuration from dictionary.
- Parameters:
- Returns:
DaskSetupConfig instance
- Return type:
- merge_overrides(overrides)[source]
Apply a dict of explicitly-named field overrides on top of this configuration.
Unlike
merge_with(), only the keys actually present in overrides are applied. This is the right tool for merging caller-supplied keyword arguments: building a throwawayDaskSetupConfigfrom them would also carry ~20 untouched dataclass defaults, which would silently overwrite the profile or config object being merged into.- Parameters:
overrides (dict[str, Any] | None) – Mapping of field name -> value. Only these fields are changed.
Noneor an empty dict is a no-op. Unknown keys are ignored (matchingfrom_dict()). Atagsentry replaces the tag list rather than merging it.- Returns:
New merged configuration, validated as a whole.
- Return type:
- merge_with(other)[source]
Merge this configuration with another, with other taking precedence.
Every non-
Nonefield of other is applied — including fields left at their dataclass defaults. That makes this the right tool for layering two fully-specified configurations (defaults < profile), and the wrong one for applying a handful of caller keyword arguments; usemerge_overrides()for that.- Parameters:
other (DaskSetupConfig | None) – Configuration to merge (higher precedence)
- Returns:
New merged configuration
- Return type:
- class dask_setup.config_manager.ConfigManager(config_dir=None, site_profiles_dir=None)[source]
Bases:
objectManages loading and saving of configuration profiles.
- list_profiles()[source]
List all available profiles (builtin + site-wide + user).
Profiles are merged in precedence order — user profiles overwrite site-wide profiles, which overwrite builtins of the same name.
- get_profile(name, _inheritance_chain=None)[source]
Get a specific profile by name.
Precedence: user profiles → site-wide profiles → builtins, so a profile you save shadows a builtin of the same name. This matches
list_profiles(), and therefore whatdask-setup listanddask-setup showdisplay.
- save_profile(profile)[source]
Save a profile to disk.
The current
PROFILE_FORMAT_VERSIONis always written to theversionfield so that future versions ofdask_setupcan detect and warn about profiles created by newer releases.- Parameters:
profile (ConfigProfile) – Profile to save
- Raises:
InvalidConfigurationError – If trying to save builtin profile or validation fails
- Return type:
None
- delete_profile(name)[source]
Delete a user profile.
- Parameters:
name (str) – Profile name to delete
- Returns:
True if deleted, False if not found
- Raises:
InvalidConfigurationError – If trying to delete builtin profile
- Return type:
- load_profile_from_file(file_path, _inheritance_chain=None)[source]
Load a profile from a YAML file, resolving any
based_oninheritance.- Parameters:
- Returns:
Fully resolved profile (with inherited config already merged in).
- Return type:
ConfigProfile
- Raises:
InvalidConfigurationError – If the file is unreadable, contains invalid YAML, references a non-existent parent, or has a circular
based_onchain.
- import_profile_from_url(url, name_override=None, force=False)[source]
Fetch a YAML profile from url and install it as a user profile.
- Parameters:
url (str) – HTTP/HTTPS URL that returns a raw YAML profile file.
name_override (str | None) – If provided, the profile is saved under this name instead of the name embedded in the YAML file.
force (bool) – If
True, overwrite an existing profile of the same name. IfFalse(default), raiseInvalidConfigurationErrorwhen the target name already exists.
- Returns:
The imported (and saved) profile.
- Return type:
ConfigProfile
- Raises:
InvalidConfigurationError – If the URL cannot be fetched, the content is invalid, or the profile name already exists and force is
False.
- static get_profile_schema()[source]
Return the JSON Schema for the profile YAML format.
The schema can be used by editors (VS Code, PyCharm, etc.) for autocompletion and inline validation of
.yamlprofile files.- Returns:
A JSON Schema (draft-07) describing the profile YAML structure.
- Return type:
- auto_select_profile(resources=None)[source]
Select the most appropriate builtin profile for the current environment.
Inspects PBS/SLURM environment variables, detected resources, and the runtime environment (e.g. Jupyter) to pick a named profile.
This is called automatically when
profile="auto"is passed tosetup_dask_client().- Parameters:
resources (ResourceSpec or None) – Detected system resources. When
None, the method falls back to environment variable inspection only.- Returns:
Name of the selected builtin profile. Always one of the builtin profile names (guaranteed to exist in
builtin_profiles).- Return type:
Notes
Selection logic (first match wins):
Jupyter environment →
"interactive"Small machine (≤ 8 cores or ≤ 16 GiB total RAM) →
"development"I/O-heavy PBS job (
$PBS_JOBFSset,≥ 16 cores) →"zarr_io_heavy"Large climate/science HPC job (
≥ 48 coresor≥ 128 GiB) →"climate_analysis"General HPC job with substantial resources →
"production"Fallback →
"development"
Multi-node
- class dask_setup.multinode.MultiNodeConfig(workload_type='cpu', workers_per_node=1, cores_per_worker=1, mem_per_worker_gb=4.0, walltime='01:00:00', queue='normal', project=None, job_extra_directives=<factory>, n_nodes=1, shared_tmp_dir=None, env_extra=<factory>, scheduler_options=<factory>, reserve_mem_gb=4.0, adaptive=False, min_jobs=1, max_jobs=10)[source]
Bases:
objectConfiguration for a multi-node
dask-jobqueuecluster.This is a companion to
DaskSetupConfigthat adds the fields needed to submit worker jobs to PBS or SLURM. The single-nodeDaskSetupConfigfields (workload_type,reserve_mem_gb, etc.) are accepted here too so callers can use one object for both paths.- Parameters:
workload_type (str) – Worker topology —
"cpu","io","mixed", or"gpu". Passed through to the single-node topology logic when decidingcores_per_workerandthreads_per_worker.workers_per_node (int) – Number of Dask worker processes to start per submitted job. Typically 1 per GPU for GPU workloads, or
ncpus / cores_per_workerfor CPU workloads.cores_per_worker (int) – CPU cores allocated to each worker. For PBS this maps to
-l ncpus=cores_per_worker * workers_per_node.mem_per_worker_gb (float) – RAM in GiB to request per worker process. The total node request is
mem_per_worker_gb * workers_per_node.walltime (str) – Job walltime string in
HH:MM:SSformat.queue (str) – Scheduler queue / partition to submit to.
project (str | None) – PBS/SLURM project / account string (maps to
-P/--account).job_extra_directives (list[str]) – Additional
#PBSor#SBATCHdirectives to inject verbatim into the job script header.n_nodes (int) – Number of nodes to request. Defaults to
1(scale up by adding more jobs, not more nodes per job).shared_tmp_dir (str | pathlib.Path | None) – Path to a Lustre / GPFS shared directory for stores that must be visible to all workers (e.g. Rechunker targets). When
None, per-node temp is used.env_extra (list[str]) – Extra shell lines inserted verbatim near the top of worker job scripts, before the worker starts – e.g.
["module load conda/analysis3", "export OMP_NUM_THREADS=1"]. Write the full statement including anyexport; the lines are not modified. This matches dask-jobqueue’sjob_script_prologue, which is where they end up.scheduler_options (dict[str, Any]) – Options forwarded verbatim to
dask-jobqueue’sscheduler_optionsparameter.reserve_mem_gb (float) – OS memory reservation per node (for compatibility with single-node config objects). Defaults to
4.0in multi-node mode (the OS footprint on a dedicated compute node is small).adaptive (bool) – Enable adaptive (elastic) scaling via
cluster.adapt(minimum=min_jobs, maximum=max_jobs).min_jobs (int) – Minimum active jobs when adaptive is
True.max_jobs (int) – Maximum active jobs when adaptive is
True.
Bases:
objectA shared temporary directory visible to all nodes in the job.
On multi-node PBS/SLURM jobs,
$PBS_JOBFSis per-node and cannot be used as a shared store (e.g. for Rechunker targets). This helper wraps a Lustre / GPFS / Scratch path that is visible cluster-wide.- Parameters:
path (str | pathlib.Path) – Absolute path to the shared filesystem directory to use.
create_subdirectory (bool) – If
True(default), create a uniquedask_tmp_<jobid>subdirectory inside path to avoid collisions across concurrent jobs.cleanup_on_close (bool) – If
True, delete the directory tree whencleanup()is called. Defaults toFalse— shared scratch is typically cleaned by the scheduler.
The actual directory that was created (may include the subdirectory).
- Type:
Path
Remove the temporary directory if cleanup_on_close is
True.- Return type:
None
- dask_setup.multinode.detect_cluster_mode()[source]
Detect the appropriate cluster mode from the execution environment.
Distinguishes between batch jobs (where submitting child worker jobs via dask-jobqueue is the right approach) and interactive jobs (where the resources are already allocated and workers should be started directly).
PBS sets
PBS_ENVIRONMENT=PBS_INTERACTIVEfor interactive jobs (qsub -I). SLURM setsSLURM_JOB_NAME=interactiveor the job was submitted viasalloc(SLURM_JOB_IDis set butSLURM_BATCH_FLAGis absent or0).- Returns:
One of
"pbs","slurm","interactive", or"local"."interactive"is returned when inside a PBS interactive job (PBS_ENVIRONMENT=PBS_INTERACTIVE) or a SLURM interactive allocation (salloc/SLURM_BATCH_FLAGnot set). In this mode,setup_interactive_cluster()should be used instead ofsetup_pbs_cluster()/setup_slurm_cluster().- Return type:
- dask_setup.multinode.setup_interactive_cluster(workload_type='cpu', workers_per_node=None, threads_per_worker=None, wait_for_workers=True, worker_timeout=60.0, scheduler_port=8786, config=None)[source]
Set up a Dask cluster using resources already allocated in an interactive job.
This is the right function to call from a Jupyter notebook running inside a
qsub -I(PBS) orsalloc(SLURM) interactive session. Unlikesetup_pbs_cluster()/setup_slurm_cluster(), it does not submit new batch jobs — it creates workers directly on the nodes that PBS or SLURM has already assigned to the current session.Behaviour
Single allocated node — creates a
LocalClusterusing all cores and memory available in the allocation (readsPBS_NCPUS/PBS_MEMor SLURM equivalents viadetect_resources()).Multiple allocated nodes — creates a
dask.distributed.SSHClusteracross all nodes listed inPBS_NODEFILE/$SLURM_NODELIST. Passwordless SSH between nodes is required (standard on most HPC systems).
- param workload_type:
Worker topology —
"cpu","io","mixed", or"auto". Determines threads per worker and workers per node using the same logic as single-nodesetup_dask_client().- param workers_per_node:
Override the number of worker processes to start per node. When
None(default), derived from workload_type and the core count.- param threads_per_worker:
Override threads per worker process. When
None, derived from workload_type.- param wait_for_workers:
Block until at least one worker has connected. Defaults to
True.- param worker_timeout:
Seconds to wait for workers. Defaults to 60 s (workers start almost immediately because no job submission is involved).
- param scheduler_port:
Port for the Dask scheduler (multi-node SSH path only).
- returns:
client— a connecteddask.distributed.Client.cluster—LocalClusterorSSHCluster.tmp_path— path to the temporary directory, or""when not set.- rtype:
(client, cluster, tmp_path)
- dask_setup.multinode.setup_pbs_cluster(config=None, *, workload_type=None, workers_per_node=None, cores_per_worker=None, mem_per_worker_gb=None, walltime=None, queue=None, project=None, job_extra_directives=None, n_nodes=None, shared_tmp_dir=None, env_extra=None, adaptive=None, min_jobs=None, max_jobs=None, n_workers=1, wait_for_workers=True, worker_timeout=300.0)[source]
Set up a multi-node Dask cluster backed by PBS/Torque.
Uses
dask-jobqueue.PBSClusterunder the hood, applyingMultiNodeConfigdefaults and the same error-handling conventions as single-nodesetup_dask_client().- Parameters:
config (MultiNodeConfig | None) – A
MultiNodeConfiginstance. IfNone, a default one is constructed from the keyword arguments.workload_type (str | None) – Convenience overrides for any
MultiNodeConfigfield.workers_per_node (int | None) – Convenience overrides for any
MultiNodeConfigfield.… – Convenience overrides for any
MultiNodeConfigfield.n_workers (int) – Number of worker jobs to submit immediately (before any adaptive scaling kicks in).
wait_for_workers (bool) – If
True(default), block until at least one worker has connected to the scheduler before returning. This prevents the client from appearing to have 0 workers when PBS has not yet started the submitted jobs. Set toFalseto return immediately and pollclient.wait_for_workers()yourself.worker_timeout (float) – Seconds to wait for workers to come online when wait_for_workers is
True. Defaults to 300 s (5 minutes). Raise this on queues with long wait times. ATimeoutErroris raised (with a diagnostic message) if no workers connect within this window.cores_per_worker (int | None)
mem_per_worker_gb (float | None)
walltime (str | None)
queue (str | None)
project (str | None)
n_nodes (int | None)
adaptive (bool | None)
min_jobs (int | None)
max_jobs (int | None)
- Returns:
client— a connecteddask.distributed.Client.cluster— the livePBSClusterobject.shared_tmp— aSharedTempDirorNone.- Return type:
(client, cluster, shared_tmp)
- dask_setup.multinode.setup_slurm_cluster(config=None, *, workload_type=None, workers_per_node=None, cores_per_worker=None, mem_per_worker_gb=None, walltime=None, queue=None, project=None, job_extra_directives=None, n_nodes=None, shared_tmp_dir=None, env_extra=None, adaptive=None, min_jobs=None, max_jobs=None, n_workers=1, wait_for_workers=True, worker_timeout=300.0)[source]
Set up a multi-node Dask cluster backed by SLURM.
Uses
dask-jobqueue.SLURMClusterunder the hood. Mirrors the API ofsetup_pbs_cluster().- Parameters:
config (MultiNodeConfig | None) – A
MultiNodeConfiginstance.n_workers (int) – Number of worker jobs to submit immediately.
wait_for_workers (bool) – If
True(default), block until at least one worker has connected to the scheduler before returning. Set toFalseto return immediately.worker_timeout (float) – Seconds to wait for workers to come online. Defaults to 300 s.
workload_type (str | None)
workers_per_node (int | None)
cores_per_worker (int | None)
mem_per_worker_gb (float | None)
walltime (str | None)
queue (str | None)
project (str | None)
n_nodes (int | None)
adaptive (bool | None)
min_jobs (int | None)
max_jobs (int | None)
- Return type:
(client, cluster, shared_tmp)
- dask_setup.multinode.generate_pbs_script(cfg, script_path, python_executable='python3', dask_setup_args='')[source]
Generate a PBS job script string that launches a dask_setup-based job.
- Parameters:
cfg (MultiNodeConfig) – Multi-node configuration.
script_path (str) – Path to the user’s Python script to run.
python_executable (str) – Python interpreter to use (default
python3).dask_setup_args (str) – Additional arguments to pass to the script.
- Returns:
Complete
#PBSjob script content.- Return type:
- dask_setup.multinode.generate_slurm_script(cfg, script_path, python_executable='python3', dask_setup_args='')[source]
Generate a SLURM job script string.
- Parameters:
cfg (MultiNodeConfig) – Multi-node configuration.
script_path (str) – Path to the user’s Python script to run.
python_executable (str) – Python interpreter to use (default
python3).dask_setup_args (str) – Additional arguments to pass to the script.
- Returns:
Complete
#SBATCHjob script content.- Return type:
Chunking and xarray
- dask_setup.xarray.recommend_chunks(ds, client=None, workload_type='auto', target_chunk_mb=(256, 512), safety_factor=0.6, verbose=False, storage_format=None, storage_path=None, chunk_domain=None, **kwargs)[source]
Recommend optimal chunk sizes for an xarray Dataset or DataArray.
Analyzes the dataset characteristics and available Dask worker resources to suggest chunk sizes that balance memory efficiency with good parallelization. Optionally considers storage format for I/O-optimized chunking.
- Parameters:
ds (xr.Dataset | xr.DataArray) – xarray Dataset or DataArray to analyze
client (Client | None) – Active Dask client (to detect worker configuration), or None to use system defaults
workload_type (str) – Chunking strategy - “cpu” (compute-heavy), “io” (I/O-heavy), “mixed” (balanced), or “auto” (detect automatically)
target_chunk_mb (tuple[float, float]) – (min, max) target chunk size in MiB. Default: (256, 512)
safety_factor (float) – Fraction of worker memory to use for chunks. Default: 0.6 (60%)
verbose (bool) – If True, print detailed report and return ChunkRecommendation object. If False, return simple dict of chunk sizes.
storage_format (str | None) – Optional storage format hint (“zarr”, “netcdf”) for I/O optimization
storage_path (str | None) – Optional storage path/URL for format detection and location optimization
chunk_domain (str | None) –
Optional axis family to restrict chunking to.
"spatial"— only chunk spatial dimensions (lat, lon, x, y, …); all temporal dimensions (time, date, step, …) are loaded fully into a single chunk (equivalent tods.chunk({"time": -1, ...}))."temporal"— only chunk temporal dimensions; all spatial dimensions are loaded fully into a single chunk.None(default) — no constraint, the existing behaviour applies and all dimensions are candidates for chunking.**kwargs (Any) – Additional parameters (reserved for future use)
- Returns:
A dict mapping dimension names to recommended chunk sizes (locked dimensions appear as
-1) whenverbose=False; a ChunkRecommendation object with full details whenverbose=True.- Raises:
XarrayDependencyError – If xarray or numpy are not installed
ValueError – If
chunk_domainis not one of the accepted values
- Return type:
Examples
Basic usage: >>> chunks = recommend_chunks(ds, client) >>> ds_chunked = ds.chunk(chunks)
With detailed analysis: >>> recommendation = recommend_chunks(ds, client, verbose=True) >>> print(recommendation) # Shows detailed report >>> ds_chunked = ds.chunk(recommendation.chunks)
For I/O-heavy workloads: >>> chunks = recommend_chunks(ds, workload_type=”io”)
Chunk only spatial dims, load all time into memory: >>> chunks = recommend_chunks(ds, client, chunk_domain=”spatial”) >>> # chunks == {“lat”: 256, “lon”: 512, “time”: -1} >>> ds_chunked = ds.chunk(chunks)
Chunk only the time axis, load all spatial points into memory: >>> chunks = recommend_chunks(ds, client, chunk_domain=”temporal”) >>> # chunks == {“time”: 120, “lat”: -1, “lon”: -1} >>> ds_chunked = ds.chunk(chunks)
- dask_setup.xarray.validate_chunks(ds, client=None, max_chunk_ratio=0.5, min_chunk_mb=10.0)[source]
Validate existing chunk sizes against cluster memory limits.
Compares each dimension’s current chunk size to the per-worker memory available in the cluster, and warns when chunks are dangerously large (OOM risk) or very small (high task-graph overhead).
This function is called automatically by
setup_dask_client()when a dataset is passed via theds=parameter.- Parameters:
ds (xr.Dataset or xr.DataArray) – Dataset with existing chunking to validate.
client (dask.distributed.Client or None) – Active Dask client used to read per-worker memory limits. When None, falls back to system psutil memory detection.
max_chunk_ratio (float) – Maximum acceptable fraction of per-worker memory per chunk. Default 0.5 — chunks larger than 50 % of worker memory trigger a warning.
min_chunk_mb (float) – Minimum acceptable chunk size in MiB. Default 10 MiB. Chunks smaller than this trigger a task-overhead warning.
- Returns:
Warning messages (empty list if no issues found). The same messages are also emitted via
warnings.warn()so they appear in logs.- Return type:
Examples
issues = validate_chunks(ds, client) if issues: chunks = recommend_chunks(ds, client) ds = ds.chunk(chunks)
- class dask_setup.xarray.ChunkRecommendation(chunks, estimated_chunk_mb, total_chunks, warnings_list=None, dataset_info=None)[source]
Bases:
objectContainer for chunk recommendation results.
- dask_setup.rechunk.rechunk_dataset(ds, target_chunks, client, dask_tmp, output_path=None, max_mem='2GB', cleanup_temp=True)[source]
Rechunk an xarray Dataset using rechunker with HPC-friendly temp placement.
Wraps the
rechunkerlibrary to safely rechunk large datasets to new chunk shapes. Both the intermediate Zarr temp store and the final output Zarr store are written to the Dask spill/temp directory (dask_tmp), which is typically$PBS_JOBFSfast local storage on NCI Gadi.- Parameters:
ds (xr.Dataset or xr.DataArray) – Dataset to rechunk. Must be backed by dask arrays (opened lazily).
target_chunks (dict[str, int]) – Target chunk sizes, e.g.
{"time": 10, "lat": 200, "lon": 200}. Dimensions not listed keep their existing chunk sizes.client (dask.distributed.Client) – Active Dask client used to execute the rechunking task graph.
dask_tmp (str or Path) – Dask spill/temp directory — the third element returned by
setup_dask_client(). Intermediate and output stores are placed here unless output_path is specified.output_path (str, Path, or None) – Destination Zarr store path for the rechunked dataset. If
None, a timestamped subdirectory under dask_tmp is used. This path is not cleaned up automatically; it persists for the job’s lifetime.max_mem (str) – Maximum memory rechunker may use per task, e.g.
"1GB","4GB". Defaults to"2GB". Should be at most 50 % of per-worker memory.cleanup_temp (bool) – If
True(default), the rechunker intermediate temp store is deleted after rechunking completes or fails. The output store is never deleted automatically.
- Returns:
The rechunked dataset opened lazily from output_path.
- Return type:
xr.Dataset or xr.DataArray
- Raises:
ImportError – If
rechunkerorzarrare not installed.RuntimeError – If rechunking fails for any reason. Partial output is cleaned up.
Notes
Install optional dependencies with:
pip install rechunker zarr
Examples
from dask_setup import setup_dask_client, recommend_chunks, rechunk_dataset client, cluster, tmp = setup_dask_client(workload_type="io") ds = xr.open_zarr("era5.zarr") chunks = recommend_chunks(ds, client) ds_rechunked = rechunk_dataset(ds, chunks, client, tmp) ds_rechunked.to_zarr("era5_rechunked.zarr")
See also
recommend_chunksCompute optimal target_chunks for a dataset.
validate_chunksCheck whether existing chunks need rechunking.
I/O patterns
- dask_setup.io_patterns.recommend_io_chunks(ds, path_or_url=None, client=None, format_hint=None, access_pattern='auto', target_chunk_mb=(128, 512), storage_location='auto', verbose=False)[source]
Recommend I/O-optimized chunks for xarray datasets.
- Parameters:
ds (xr.Dataset | xr.DataArray) – xarray Dataset or DataArray to optimize
path_or_url (str | None) – Optional path/URL to determine storage format and location
client (Client | None) – Optional Dask client for cluster info
format_hint (str | None) – Optional format override (“zarr”, “netcdf”, etc.)
access_pattern (str) – Access pattern hint (“sequential”, “random”, “streaming”, “compute”, “auto”)
target_chunk_mb (tuple[float, float]) – Target chunk size range in MiB
storage_location (str) – Storage location hint (“local”, “cloud”, “network”, “auto”)
verbose (bool) – If True, return full IORecommendation object
- Returns:
IORecommendation object if verbose=True, else dict of chunk recommendations
- Return type:
IORecommendation | dict[str, int]
- dask_setup.io_patterns.detect_storage_format(path_or_url, ds=None)[source]
Detect storage format from path/URL and optional xarray object.
- Parameters:
- Returns:
"zarr_v3","zarr","netcdf","kerchunk", or"unknown"."zarr_v3"is returned for zarr-python ≥ 3.0 stores;"kerchunk"is returned for Kerchunk / VirtualiZarr reference stores (checked before zarr, since those stores present a zarr-like interface).- Return type:
Format name
- class dask_setup.io_patterns.IORecommendation(format, chunks, compression, storage_options, access_pattern, estimated_throughput_mb_s, warnings, extra=<factory>)[source]
Bases:
objectContainer for I/O optimization recommendations.
- Parameters:
- class dask_setup.io_patterns.ZarrOptimizer(client=None)[source]
Bases:
IOOptimizerOptimizer for Zarr format storage.
- Parameters:
client (Client | None)
- optimize_chunks(ds, target_chunk_mb=(128, 512), access_pattern='auto')[source]
Optimize chunks for Zarr format.
- class dask_setup.io_patterns.ZarrV3Optimizer(client=None)[source]
Bases:
IOOptimizerOptimizer for Zarr v3 format storage (zarr-python ≥ 3.0).
Handles the updated
zarr.open()interface, sharding viazarr.codecs.ShardingCodec, and the new codec pipeline introduced inzarr>=3.0. When sharding is appropriate (large arrays), the recommended outer/inner chunk shapes are returned inIORecommendation.extra["sharding"].- Parameters:
client (Client | None)
- detect_format(path_or_url, ds=None)[source]
Detect Zarr v3 from path pattern or dataset store metadata.
- optimize_chunks(ds, target_chunk_mb=(128, 512), access_pattern='auto')[source]
Optimize outer chunk sizes for Zarr v3 (with sharding awareness).
- class dask_setup.io_patterns.NetCDFOptimizer(client=None)[source]
Bases:
IOOptimizerOptimizer for NetCDF format storage.
- Parameters:
client (Client | None)
- optimize_chunks(ds, target_chunk_mb=(64, 256), access_pattern='auto')[source]
Optimize chunks for NetCDF format.
- class dask_setup.io_patterns.KerchunkOptimizer(client=None)[source]
Bases:
IOOptimizerOptimizer for datasets opened via Kerchunk or VirtualiZarr reference stores.
When a dataset is backed by a Kerchunk / VirtualiZarr reference filesystem, chunk boundaries are fixed by the byte ranges of the original files. Rechunking would require a full data copy, defeating the purpose of the virtual store. This optimizer detects the reference-filesystem pattern, returns the existing chunks unchanged, and adds an informational warning.
- Parameters:
client (Client | None)
- detect_format(path_or_url, ds=None)[source]
Detect Kerchunk/VirtualiZarr reference filesystem datasets.
- optimize_chunks(ds, target_chunk_mb=(128, 512), access_pattern='auto')[source]
Return the existing chunks — rechunking a Kerchunk dataset is a no-op.
- dask_setup.parquet.recommend_parquet_chunks(df, client=None, path_or_url=None, target_partition_mb=(128.0, 512.0), compression='auto', storage_location='auto', verbose=False)[source]
Recommend partition sizes for Dask DataFrame Parquet workloads.
- Parameters:
df (Any) – A Dask or pandas DataFrame (or any object with
dtypes,columns, and optionallymemory_usage()).client (Client | None) – Optional Dask
Client. When provided, per-worker memory limits are used to tighten the upper partition bound.path_or_url (str | None) – Destination path or URL. Used to infer storage location and to recommend appropriate
storage_options.target_partition_mb (tuple[float, float]) –
(min_mb, max_mb)target partition size range. Defaults to(128, 512).compression (str) – Parquet compression codec.
"auto"picks"snappy"for local storage and"zstd"for cloud / network.storage_location (str) – One of
"local","cloud","network", or"auto".verbose (bool) – If
True, return the fullParquetRecommendationand print a report. IfFalse(default), returnrows_per_partitiononly.
- Returns:
ParquetRecommendationwhen verbose isTrue, otherwise therecommended
rows_per_partitionas anint.
- Return type:
- class dask_setup.parquet.ParquetRecommendation(rows_per_partition, compression, storage_options, estimated_partition_mb, warnings, extra=<factory>)[source]
Bases:
objectContainer for Parquet / Arrow partition recommendations.
- Parameters:
- compression
Recommended compression codec and options dict, suitable for passing to
dask.dataframe.to_parquet(..., compression=...).- Type:
- storage_options
Recommended
storage_optionsdict for cloud or network targets.
- estimated_partition_mb
Estimated size of each partition in MiB after applying the recommended row count.
- Type:
Workload inference and tuning
- dask_setup.workload.infer_workload_type(ds=None)[source]
Infer the most appropriate workload type from a dataset’s structure.
Examines variable dtypes, dimension names, and array sizes to decide whether the workload is primarily:
CPU-bound (→
"cpu"): Many floating-point variables, scientific dimension names (time/lat/lon/lev), large arrays per variable.I/O-bound (→
"io"): Mostly integer / byte / bool variables, many small variables typical of lookup tables or mask datasets.Mixed (→
"mixed"): When the signal is ambiguous or no dataset is provided.
- Parameters:
ds (xr.Dataset, xr.DataArray, or None) – Dataset to inspect. When
None, returns"mixed"immediately.- Returns:
One of
"cpu","io", or"mixed".- Return type:
Notes
The heuristic is intentionally conservative — it returns
"mixed"when the evidence is not strong (score difference ≤ 2). Users can always override with an explicitworkload_type=argument.The signal tables are tuned for CF-convention geoscience / climate datasets (the primary NCI Gadi use-case) but are general enough for most scientific array workloads.
Examples
import xarray as xr from dask_setup import infer_workload_type ds = xr.open_zarr("era5.zarr") wt = infer_workload_type(ds) # likely "cpu" client, cluster, tmp = setup_dask_client(workload_type=wt)
- dask_setup.tune.tune_memory_thresholds(client, strategy='auto', spill_threshold_gib=0.5, tighten_by=0.05, loosen_by=0.05)[source]
Adjust Dask worker memory thresholds based on observed spill behaviour.
Reads current spill metrics from the scheduler, then applies threshold adjustments on every worker:
No / low spilling (spill < spill_threshold_gib): tighten
memory.targetandmemory.spilldownward by tighten_by so workers retain more head-room before the GC kicks in.Heavy spilling (spill ≥ spill_threshold_gib): loosen the same thresholds upward by loosen_by so workers buffer more data in RAM before reaching the spill threshold, reducing disk write amplification.
Adjustments are clamped to safe ranges: target ∈ [0.40, 0.90], spill ∈ [0.50, 0.95]. If the current value is already at the boundary no change is applied.
- Parameters:
client (dask.distributed.Client) – A connected Dask client. The scheduler must still be reachable.
strategy ({"auto", "tighten", "loosen", "off"}) –
"auto"(default) reads spill stats and chooses the direction."tighten"/"loosen"force the direction regardless."off"returns immediately without making any changes.spill_threshold_gib (float) – Spill volume (GiB) above which
"auto"mode switches to the loosen direction. Default: 0.5 GiB.tighten_by (float) – Fraction to reduce thresholds by when tightening (default 0.05 = 5 pp).
loosen_by (float) – Fraction to increase thresholds by when loosening (default 0.05 = 5 pp).
- Returns:
Snapshot of what changed and why. Call
.summary()for a one-liner suitable for logging.- Return type:
Examples
from dask_setup import setup_dask_client, tune_memory_thresholds client, cluster, tmp = setup_dask_client() # Run a sample batch of tasks first client.compute(ds.isel(time=slice(0, 10)).mean()).result() # Now tune based on what was observed result = tune_memory_thresholds(client) print(result.summary())
- class dask_setup.tune.MemoryTuneResult(strategy, old_target, new_target, old_spill, new_spill, spill_gib_observed, rationale, workers_updated)[source]
Bases:
objectResult from a memory threshold tuning pass.
- Parameters:
- workers_updated
Number of workers whose thresholds were successfully updated.
0if no change was needed or if the update failed.- Type:
- dask_setup.callbacks.register_worker_callbacks(client, on_worker_death=None, on_worker_added=None)[source]
Register callbacks for worker lifecycle events on a Dask cluster.
Installs a
SchedulerPluginthat calls user-supplied functions when workers join or leave the cluster.- Parameters:
client (dask.distributed.Client) – A connected Dask client.
on_worker_death (callable(worker_addr: str) | None) – Called when a worker is removed from the scheduler — whether it crashed, was explicitly closed, or was scaled down.
worker_addris the worker’s TCP address string (e.g."tcp://127.0.0.1:12345").on_worker_added (callable(worker_addr: str) | None) – Called when a new worker connects to the scheduler.
- Return type:
None
Notes
If neither callback is provided this function is a no-op.
The plugin is registered with
name="dask_setup_worker_health". Calling this function a second time replaces the existing plugin (idempotent where supported by the installed Dask version).Exceptions raised inside callbacks are caught and logged as warnings so that a buggy callback never crashes the scheduler.
Examples
import threading from dask_setup import setup_dask_client, register_worker_callbacks dead: list[str] = [] _lock = threading.Lock() def on_death(addr: str) -> None: with _lock: dead.append(addr) client, cluster, tmp = setup_dask_client() register_worker_callbacks(client, on_worker_death=on_death) # ... run tasks ... if dead: print(f"Workers that died during the run: {dead}")
Reporting
- dask_setup.reporting.cluster_report(client, start_time=None)[source]
Collect post-run statistics from a connected Dask client.
Queries the distributed scheduler for per-worker memory, spill volume, and task counts. All metric collection is done defensively — any field that cannot be retrieved (e.g. because this Dask version does not expose the metric) is left at its zero/empty default rather than raising.
- Parameters:
client (dask.distributed.Client) – A connected Dask client. The scheduler must still be reachable; call this function before
client.close().start_time (float or None) – Wall-clock start time as returned by
time.monotonic(). When provided,ClusterReport.wall_time_secondsis computed astime.monotonic() - start_time. PassNone(the default) to leavewall_time_secondsat0.0.
- Returns:
Snapshot of cluster metrics at the time of the call.
- Return type:
Examples
import time from dask_setup import setup_dask_client, cluster_report t0 = time.monotonic() client, cluster, tmp = setup_dask_client() # ... do work ... report = cluster_report(client, start_time=t0) print(report.summary_line())
- class dask_setup.reporting.ClusterReport(wall_time_seconds=0.0, memory_per_worker_gib=<factory>, total_spill_gib=0.0, total_tasks=0)[source]
Bases:
objectSummary statistics collected from a Dask cluster at close time.
- Parameters:
- wall_time_seconds
Elapsed wall-clock time since the cluster was started (or since the start_time passed to
cluster_report()).0.0if no start time was provided.- Type:
- memory_per_worker_gib
Managed data held in memory (GiB) per worker address, sampled at report time. Data spilled to disk is excluded; it is counted in total_spill_gib instead. Keys are worker addresses (e.g.
"tcp://127.0.0.1:12345").
- total_spill_gib
Total bytes written to disk spill storage across all workers (GiB).
0.0if spill metrics are unavailable in this Dask version.- Type:
- total_tasks
Number of tasks present in the scheduler graph at report time. This is a snapshot — it is not an all-time cumulative count.
- Type:
Benchmarking
- dask_setup.benchmark.benchmark_config(configs, ds, operation='mean', *, repeats=1, warmup=False, fallback_on_detection_failure=True, verbose=False)[source]
A/B-test multiple configurations against the same xarray operation.
Each configuration is run in a fresh cluster so that memory state, worker topology, and spill behaviour are fully independent between runs.
- Parameters:
configs (dict[str, DaskSetupConfig] | list[DaskSetupConfig] | DaskSetupConfig) –
Configurations to compare. May be:
A
dict[name, DaskSetupConfig]— explicit names.A
list[DaskSetupConfig]— names are"config_0", etc.A single
DaskSetupConfig— returns a one-element list.
ds (Any) – xarray Dataset or DataArray to benchmark against. Should not already be chunked —
benchmark_config()will chunk it according to each config’s recommended chunks (or leave it as-is if no chunking is suggested).operation (Callable[[Any], Any] | str) – Operation to time. Either a callable
fn(ds) -> lazy_resultor one of the string aliases:"mean","sum","std","max","min","var","rechunk".repeats (int) – Number of timed repetitions per configuration. Mean and std-dev of wall time are stored in each
BenchmarkResult.warmup (bool) – If
True, run one un-timed warmup pass before the timed repeats. Useful for eliminating cold-start overhead (e.g. JIT compilation).fallback_on_detection_failure (bool) – Passed to
setup_dask_client().verbose (bool) – If
True, print a summary line after each configuration completes.
- Returns:
One entry per configuration, in the same order as configs.
- Return type:
Examples
from dask_setup import DaskSetupConfig from dask_setup.benchmark import benchmark_config results = benchmark_config( { "io": DaskSetupConfig(workload_type="io"), "cpu": DaskSetupConfig(workload_type="cpu"), }, my_ds, operation="mean", repeats=3, ) for r in sorted(results, key=lambda r: r.wall_time_seconds): print(r.summary_line())
- dask_setup.benchmark.scaling_analysis(ds, operation='mean', worker_counts=(1, 2, 4, 8), *, base_config=None, repeats=1, warmup=False, fallback_on_detection_failure=True, mode='local', plot=False, verbose=False)[source]
Measure parallel scaling across different worker counts.
For each entry in worker_counts, a fresh local cluster is created with
max_workersset to that count and the operation is timed. The resultingScalingResultincludes speedup and efficiency relative to the single-worker baseline.- Parameters:
ds (Any) – xarray Dataset or DataArray to benchmark.
operation (Callable[[Any], Any] | str) – Callable or string alias (see
benchmark_config()).worker_counts (Sequence[int]) – Sequence of worker counts to sweep. The first entry is used as the baseline for speedup calculations.
base_config (DaskSetupConfig | None) – Base
DaskSetupConfigto use for each run.max_workersis overridden per run. Defaults toDaskSetupConfig()(library defaults).repeats (int) – Timed repetitions per worker count.
warmup (bool) – Run one un-timed warmup pass before timing.
fallback_on_detection_failure (bool) – Passed to
setup_dask_client().mode (str) – Cluster mode passed to
setup_dask_client(). Defaults to"local"so that the sweep always uses aLocalClusteron the current node — this prevents auto-detection from dispatching to PBS/SLURM and submitting child scheduler jobs, which would time out and produce NaN results. Pass"auto"only if you specifically want multi-node dispatch for each sweep step.plot (bool) – If
True, callScalingResult.plot()and display the figure (requires matplotlib).verbose (bool) – Print a summary line after each worker count.
- Returns:
Scaling metrics for all worker counts.
- Return type:
- dask_setup.benchmark.chunk_impact(ds, client, operation='mean', chunk_sizes=None, *, auto_chunks=True, repeats=1, warmup=False, plot=False, verbose=False)[source]
Sweep chunk sizes on a fixed cluster to find the throughput sweet spot.
Unlike
benchmark_config()andscaling_analysis(), this function does not create or destroy clusters — it uses the client you provide. The dataset is rechunked before each measurement.- Parameters:
ds (Any) – xarray Dataset or DataArray. Must have known dimension sizes.
client (Client) – Connected Dask client. The cluster remains running throughout.
operation (Callable[[Any], Any] | str) – Callable or string alias (see
benchmark_config()).chunk_sizes (list[dict[str, int]] | None) – List of chunk-size dicts to try (e.g.
[{"time": 10, "lat": 50}, {"time": 20, "lat": 100}]). IfNoneandauto_chunks=True, a geometric series of five sizes is generated automatically.auto_chunks (bool) – Generate chunk sizes automatically when chunk_sizes is
None.repeats (int) – Timed repetitions per chunk size.
warmup (bool) – Run one un-timed warmup pass per chunk size.
plot (bool) – Display the wall-time vs chunk-size plot (requires matplotlib).
verbose (bool) – Print a summary line after each chunk size is tested.
- Returns:
Timing results for each chunk spec, plus the recommended spec.
- Return type:
- dask_setup.benchmark.run_synthetic_benchmark(profile_name='development', operation='mean', ds_size='small', repeats=1, fallback_on_detection_failure=True, verbose=False)[source]
Run a synthetic benchmark using
dask.array(no xarray required).Creates a random floating-point array of the given size, sets up a Dask cluster from the named profile, and times the requested operation.
This function is the backend for the
dask-setup benchmarkCLI subcommand.- Parameters:
profile_name (str) – Name of a builtin or user profile to use.
"development"is the safe default for quick tests.operation (str) – One of
"mean","sum","std","max","min".ds_size (str) – One of
"tiny","small","medium","large".repeats (int) – Timed repetitions.
fallback_on_detection_failure (bool) – Passed to
setup_dask_client().verbose (bool) – Print progress messages.
- Return type:
SyntheticBenchmarkResult
- class dask_setup.benchmark.BenchmarkResult(name, wall_time_seconds, wall_time_std=0.0, peak_memory_gib=0.0, spill_gib=0.0, n_tasks=0, n_workers=0, tasks_per_second=0.0, errors=<factory>, extra=<factory>)[source]
Bases:
objectMetrics for a single benchmarked configuration / parameter setting.
- Parameters:
- peak_memory_gib
Highest total worker process memory (RSS summed across workers) observed during the timed runs, sampled every 0.2 s. If in-flight sampling was unavailable this falls back to a post-run reading and an explanatory note is appended to
errors.- Type:
- extra
Additional metadata attached by the calling function (e.g.
{"chunk_size_mb": 128}fromchunk_impact()).
- class dask_setup.benchmark.ScalingResult(results, worker_counts, speedups, efficiencies)[source]
Bases:
objectResults of a worker-count scaling sweep.
- Parameters:
- results
One entry per worker count, in the order they were benchmarked.
- Type:
- property wall_times: list[float]
Wall times in the same order as
worker_counts.
- to_dataframe()[source]
Return results as a
pandas.DataFrame.Raises
ImportErrorif pandas is not installed.- Return type:
- class dask_setup.benchmark.ChunkImpactResult(results, chunk_specs, recommended_chunks=None)[source]
Bases:
objectResults of a chunk-size sweep on a fixed cluster.
- Parameters:
- results
One entry per chunk specification, in the order they were tried.
- Type:
- to_dataframe()[source]
Return results as a
pandas.DataFrame.Raises
ImportErrorif pandas is not installed.- Return type:
Environment and logging
- dask_setup.environment.is_jupyter()[source]
Return
Trueif running inside a Jupyter kernel.Covers JupyterLab, classic Jupyter Notebook, VSCode notebooks, Google Colab, and any other environment that uses a ZMQ kernel.
The result is cached after the first call so it is safe to call repeatedly inside hot paths.
- Return type:
Examples
from dask_setup.environment import is_jupyter if is_jupyter(): print("Running in Jupyter")
- dask_setup.environment.get_environment_type()[source]
Return a string describing the detected runtime environment.
- Returns:
str – One of
"jupyter","ipython", or"script".The result is cached after the first call.
- Return type:
Errors
Custom exceptions for the dask_setup package.
- exception dask_setup.exceptions.DaskSetupError[source]
Bases:
ExceptionBase exception for all dask_setup errors.
- exception dask_setup.exceptions.InsufficientResourcesError(required_mem, available_mem, suggested_actions=None)[source]
Bases:
DaskSetupErrorRaised when system resources are insufficient for the requested configuration.
- exception dask_setup.exceptions.InvalidConfigurationError[source]
Bases:
DaskSetupErrorRaised when configuration parameters are invalid.
- exception dask_setup.exceptions.ResourceDetectionError[source]
Bases:
DaskSetupErrorRaised when resource detection fails.
- class dask_setup.error_handling.ErrorContext(platform_info=<factory>, python_version=<factory>, total_memory_gb=<factory>, cpu_count=<factory>, hpc_environment=None, pbs_jobfs=<factory>, slurm_job_id=<factory>, available_dependencies=<factory>)[source]
Bases:
objectContainer for error context information.
- Parameters:
- class dask_setup.error_handling.EnhancedDaskSetupError(message, suggestions=None, context=None, documentation_url=None, error_code=None)[source]
Bases:
DaskSetupErrorBase class for enhanced dask_setup errors with rich context.
- Parameters:
- class dask_setup.error_handling.ConfigurationValidationError(field_errors, invalid_config=None, context=None)[source]
Bases:
EnhancedDaskSetupErrorEnhanced configuration validation error with specific field guidance.
- class dask_setup.error_handling.ResourceConstraintError(resource_type, required, available, units='GB', context=None)[source]
Bases:
EnhancedDaskSetupErrorEnhanced resource constraint error with HPC-aware suggestions.
- Parameters:
resource_type (str)
required (float)
available (float)
units (str)
context (ErrorContext | None)
- class dask_setup.error_handling.DependencyError(missing_package, feature, context=None, alternative_packages=None)[source]
Bases:
EnhancedDaskSetupErrorEnhanced dependency error with installation guidance.
- Parameters:
missing_package (str)
feature (str)
context (ErrorContext | None)
- class dask_setup.error_handling.StorageConfigurationError(storage_issue, storage_path=None, detected_format=None, context=None)[source]
Bases:
EnhancedDaskSetupErrorEnhanced storage configuration error with format-specific guidance.
- Parameters:
storage_issue (str)
storage_path (str | None)
detected_format (str | None)
context (ErrorContext | None)
- class dask_setup.error_handling.ClusterSetupError(setup_issue, cluster_config=None, context=None)[source]
Bases:
EnhancedDaskSetupErrorEnhanced cluster setup error with diagnostic information.
Unlike other
EnhancedDaskSetupErrorsubclasses,ClusterSetupErrorautomatically appends an environment summary (platform, Python version, memory, CPUs, and detected dependencies) to the formatted error message. This makes it easier to diagnose failures without separately callingget_diagnostic_info().- Parameters:
setup_issue (str)
context (ErrorContext | None)