pip install "dask[distributed]"★Scheduler, workers, dashboard.from dask.distributed import Client★The entry point to everything.client = Client()★Starts a local cluster + connects.client = Client("tcp://scheduler:8786")Connect to a running cluster.client.dashboard_link★Live diagnostics at:8787.client.close()Disconnect (closes aClient()cluster too).
Client★Your session — submits work, holds Futures.SchedulerThe brain (:8786): task graph + who-has-what.Worker★Runs tasks; keeps results in local RAM.NannyWatches a worker, restarts it if it dies.DashboardLive task stream & memory at:8787.
from dask.distributed import LocalClusterMulti-process cluster on your box.cluster = LocalCluster(n_workers=4, threads_per_worker=2)★Shape workers × threads.client = Client(cluster)★Connect the client to it.LocalCluster(memory_limit="4GB")Per-worker memory cap (spills over it).Client(processes=False)Threads only, in-process — easy debugging.
SSHCluster(["head", "w1", "w2"])Spin up workers over SSH.SLURMCluster(...) # PBS · LSF★HPC job queues —dask-jobqueue.KubeCluster(...)Kubernetes —dask-kubernetes.EC2Cluster() # Fargate · Azure · GCPCloud VMs —dask-cloudprovider.dask scheduler · dask worker <addr>★The CLI — wire it up by hand.
cluster.scale(20)★Fixed number of workers.cluster.adapt(minimum=1, maximum=50)★Auto-scale to the workload.client.wait_for_workers(4)Block until N workers are up.client.restart()Restart all workers, clear cluster state.client.retire_workers([...])Drain data off, then remove.client.shutdown()Stop the scheduler + all workers.
fut = client.submit(fn, x)★eagerRuns now; returns a Future immediately.futs = client.map(fn, seq)★One Future per item.client.submit(fn, fut)Chain on a Future — no gather needed.fut.result()★Block, copy the result to the client.fut.status # .done()pending·finished·error.client.submit(f, x, pure=False)For impure fns (e.g. random) — new key each call.
client.gather(futs)★Bring many results back at once.wait(futs)Block until all are finished.for f in as_completed(futs):★Handle each as soon as it finishes.fut.exception() # .traceback()Inspect a failed task.progress(futs)Live progress bar (notebook).del fut★Drop the pointer → frees worker memory.
f = client.scatter(data)★Push local data onto workers → Future.client.scatter(data, broadcast=True)Copy to every worker (shared lookup).client.gather(futs)★Pull results back to the client.x = x.persist()★Compute a collection, keep it on workers.client.compute(x)Collection → Future(s), lazily started.
df = df.persist()★Materialize across distributed RAM.client.replicate(futs, n=3)Extra copies for resilience & speed.client.rebalance()Even out memory across workers.client.who_has(fut)★Which workers hold this data.client.has_what()Keys held per worker.client.nbytes(summary=True)Memory by key type.
submit(fn, x, workers=["alice"])★Pin a task to specific workers.allow_other_workers=TrueMake the pin a soft preference.resources={"GPU": 1}★Require a resource-tagged worker.priority=10Higher priority runs first.retries=3Auto-retry a flaky task.key="step-1"Name the task (controls dedup).
client.run(setup_fn)★Run on every worker (imports, config).client.run_on_scheduler(fn)Run once on the scheduler process.client.upload_file("mymod.py")Ship local code to all workers.fire_and_forget(futs)Run even after you drop the Future.client.cancel(futs)Stop scheduled/running tasks.client.retry(futs)Re-run failed futures.
from dask.distributed import worker_clientTalk to the cluster from inside a task.with worker_client() as c:★Submit more work mid-task.secede()★Leave the thread pool while waiting — no deadlock.rejoin()Rejoin once ready to compute again.get_worker() # get_client()The worker/client running this task.
from dask.distributed import Lock, SemaphoreCluster-wide, named primitives.with Lock("resource"):★Mutual exclusion across the cluster.Semaphore(max_leases=2, name="db")★Cap concurrent access (e.g. a DB).Event("go").wait() # .set()Signal across tasks/workers.MultiLock(["a", "b"])Acquire several locks at once.
Queue("q").put(fut) # .get()★Pass Futures between tasks/clients.Variable("v").set(fut) # .get()A shared, named slot on the scheduler.client.publish_dataset(df, name="train")★Publish a collection for others to use.client.get_dataset("train")Another client picks it up — no recompute.client.list_datasets()What's published on the scheduler.
client.dashboard_link★Task stream · memory · progress (:8787).with performance_report(filename="r.html"):★Save a shareable HTML report.with get_task_stream() as ts:Capture per-task timings.client.processing()Tasks currently running per worker.client.get_worker_logs()Pull logs off the workers.client.profile(filename="p.html")Statistical profiler of recent work.
client.gather(giant)floods clientKeep big data on workers; gather summaries.client.scatter(big_local_df)bottleneckLoad with workers (read_parquet) instead.one long GIL-holding taskblocks workerStalls heartbeats — release the GIL or use processes.last future goes out of scopedata freedHold the Future or the result is dropped.Client() # at import timespawnGuard underif __name__ == "__main__":.