@@ -199,6 +199,161 @@ the user.
199
199
debugging, etc. You can even provide any config user value as a run flag
200
200
``--argument_name argument_value ``
201
201
202
+ .. _config-dask :
203
+
204
+ Dask distributed configuration
205
+ ==============================
206
+
207
+ The :ref: `preprocessor functions <preprocessor_functions >` and many of the
208
+ :ref: `Python diagnostics in ESMValTool <esmvaltool:recipes >` make use of the
209
+ :ref: `Iris <iris:iris_docs >` library to work with the data.
210
+ In Iris, data can be either :ref: `real or lazy <iris:real_and_lazy_data >`.
211
+ Lazy data is represented by `dask arrays <https://docs.dask.org/en/stable/array.html >`_.
212
+ Dask arrays consist of many small
213
+ `numpy arrays <https://numpy.org/doc/stable/user/absolute_beginners.html#what-is-an-array >`_
214
+ (called chunks) and if possible, computations are run on those small arrays in
215
+ parallel.
216
+ In order to figure out what needs to be computed when, Dask makes use of a
217
+ '`scheduler <https://docs.dask.org/en/stable/scheduling.html >`_'.
218
+ The default scheduler in Dask is rather basic, so it can only run on a single
219
+ computer and it may not always find the optimal task scheduling solution,
220
+ resulting in excessive memory use when using e.g. the
221
+ :func: `esmvalcore.preprocessor.multi_model_statistics ` preprocessor function.
222
+ Therefore it is recommended that you take a moment to configure the
223
+ `Dask distributed <https://distributed.dask.org >`_ scheduler.
224
+ A Dask scheduler and the 'workers' running the actual computations, are
225
+ collectively called a 'Dask cluster'.
226
+
227
+ In ESMValCore, the Dask cluster can configured by creating a file called
228
+ ``~/.esmvaltool/dask.yml ``, where ``~ `` is short for your home directory.
229
+ In this file, under the ``client `` keyword, the arguments to
230
+ :obj: `distributed.Client ` can be provided.
231
+ Under the ``cluster `` keyword, the type of cluster (e.g.
232
+ :obj: `distributed.LocalCluster `), as well as any arguments required to start
233
+ the cluster can be provided.
234
+ Extensive documentation on setting up Dask Clusters is available
235
+ `here <https://docs.dask.org/en/latest/deploying.html >`__.
236
+
237
+ .. warning ::
238
+
239
+ The format of the ``~/.esmvaltool/dask.yml `` configuration file is not yet
240
+ fixed and may change in the next release of ESMValCore.
241
+
242
+ .. note ::
243
+
244
+ If not all preprocessor functions support lazy data, computational
245
+ performance may be best with the default scheduler.
246
+ See `issue #674 <https://github.com/ESMValGroup/ESMValCore/issues/674 >`_ for
247
+ progress on making all preprocessor functions lazy.
248
+
249
+ **Example configurations **
250
+
251
+ *Personal computer *
252
+
253
+ Create a Dask distributed cluster on the computer running ESMValCore using
254
+ all available resources:
255
+
256
+ .. code :: yaml
257
+
258
+ cluster :
259
+ type : distributed.LocalCluster
260
+
261
+ this should work well for most personal computers.
262
+
263
+ .. note ::
264
+
265
+ Note that, if running this configuration on a shared node of an HPC cluster,
266
+ Dask will try and use as many resources it can find available, and this may
267
+ lead to overcrowding the node by a single user (you)!
268
+
269
+ *Shared computer *
270
+
271
+ Create a Dask distributed cluster on the computer running ESMValCore, with
272
+ 2 workers with 4 threads/4 GiB of memory each (8 GiB in total):
273
+
274
+ .. code :: yaml
275
+
276
+ cluster :
277
+ type : distributed.LocalCluster
278
+ n_workers : 2
279
+ threads_per_worker : 4
280
+ memory_limit : 4 GiB
281
+
282
+ this should work well for shared computers.
283
+
284
+ *Computer cluster *
285
+
286
+ Create a Dask distributed cluster on the
287
+ `Levante <https://docs.dkrz.de/doc/levante/running-jobs/index.html >`_
288
+ supercomputer using the `Dask-Jobqueue <https://jobqueue.dask.org/en/latest/ >`_
289
+ package:
290
+
291
+ .. code :: yaml
292
+
293
+ cluster :
294
+ type : dask_jobqueue.SLURMCluster
295
+ queue : shared
296
+ account : bk1088
297
+ cores : 8
298
+ memory : 7680MiB
299
+ processes : 2
300
+ interface : ib0
301
+ local_directory : " /scratch/b/b381141/dask-tmp"
302
+ n_workers : 24
303
+
304
+ This will start 24 workers with ``cores / processes = 4 `` threads each,
305
+ resulting in ``n_workers / processes = 12 `` Slurm jobs, where each Slurm job
306
+ will request 8 CPU cores and 7680 MiB of memory and start ``processes = 2 ``
307
+ workers.
308
+ This example will use the fast infiniband network connection (called ``ib0 ``
309
+ on Levante) for communication between workers running on different nodes.
310
+ It is
311
+ `important to set the right location for temporary storage <https://docs.dask.org/en/latest/deploying-hpc.html#local-storage >`__,
312
+ in this case the ``/scratch `` space is used.
313
+ It is also possible to use environmental variables to configure the temporary
314
+ storage location, if you cluster provides these.
315
+
316
+ A configuration like this should work well for larger computations where it is
317
+ advantageous to use multiple nodes in a compute cluster.
318
+ See
319
+ `Deploying Dask Clusters on High Performance Computers <https://docs.dask.org/en/latest/deploying-hpc.html >`_
320
+ for more information.
321
+
322
+ *Externally managed Dask cluster *
323
+
324
+ Use an externally managed cluster, e.g. a cluster that you started using the
325
+ `Dask Jupyterlab extension <https://github.com/dask/dask-labextension#dask-jupyterlab-extension >`_:
326
+
327
+ .. code :: yaml
328
+
329
+ client :
330
+ address : ' 127.0.0.1:8786'
331
+
332
+ See `here <https://jobqueue.dask.org/en/latest/interactive.html >`_
333
+ for an example of how to configure this on a remote system.
334
+
335
+ For debugging purposes, it can be useful to start the cluster outside of
336
+ ESMValCore because then
337
+ `Dask dashboard <https://docs.dask.org/en/stable/dashboard.html >`_ remains
338
+ available after ESMValCore has finished running.
339
+
340
+ **Advice on choosing performant configurations **
341
+
342
+ The threads within a single worker can access the same memory locations, so
343
+ they may freely pass around chunks, while communicating a chunk between workers
344
+ is done by copying it, so this is (a bit) slower.
345
+ Therefore it is beneficial for performance to have multiple threads per worker.
346
+ However, due to limitations in the CPython implementation (known as the Global
347
+ Interpreter Lock or GIL), only a single thread in a worker can execute Python
348
+ code (this limitation does not apply to compiled code called by Python code,
349
+ e.g. numpy), therefore the best performing configurations will typically not
350
+ use much more than 10 threads per worker.
351
+
352
+ Due to limitations of the NetCDF library (it is not thread-safe), only one
353
+ of the threads in a worker can read or write to a NetCDF file at a time.
354
+ Therefore, it may be beneficial to use fewer threads per worker if the
355
+ computation is very simple and the runtime is determined by the
356
+ speed with which the data can be read from and/or written to disk.
202
357
203
358
.. _config-esgf :
204
359
0 commit comments