Package: aics-dask-utils
AICS Dask UtilsDocumentation related to Dask, Distributed, and related packages.
Utility functions commonly used by AICS projects.FeaturesDistributed handler to manage various debugging or cluster configurationsDocumentation on example cluster deploymentsBasicsBefore we jump into quick starts there are some basic definitions to understand.TaskA task is a single static function to be processed. Simple enough. However, relevant to
AICS, is that when usingaicsimageio(and / ordask.array.Array), your image (ordask.array.Array) is split up intomanytasks. This is dependent on the image reader
and the size of the file you are reading. But in general it is safe to assume that each
image you read is split many thousands of tasks. If you want to see how many tasks your
image is split into you can either compute:Psuedo-code:sum(2 * size(channel) for channel if channel not in ["Y", "X"])Dask graph length:len(AICSImage.dask_data.__dask_graph__())MapApply a given function to the provided iterables as used as parameters to the function.
Givenlambda x: x + 1and[1, 2, 3], the result ofmap(func, *iterables)in this
case would be[2, 3, 4]. Usually, you are provided back an iterable offutureobjects back from amapoperation. The results from the map operation are not
guaranteed to be in the order of the iterable that went in as operations are started as
resources become available and item to item variance may result in different output
ordering.FutureAn object that will become available but is currently not defined. There is no guarantee
that the object is a valid result or an error and you should handle errors once the
future's state has resolved (usually this means after agatheroperation).GatherBlock the process from moving forward until all futures are resolved. Control flow here
would mean that you could potentially generate thousands of futures and keep moving on
locally while those futures slowly resolve but if you ever want a hard stop and wait for
some set of futures to complete, you would need gather them.Other CommentsDask tries to mirror the standard libraryconcurrent.futureswherever possible which
is what allows for this library to have simple wrappers around Dask to allow for easy
debugging as we are simply swapping outdistributed.Client.mapwithconcurrent.futures.ThreadPoolExecutor.mapfor example. If at any point in your code
you don't want to usedaskfor some reason or another, it is equally valid to useconcurrent.futures.ThreadPoolExecutororconcurrent.futures.ProcessPoolExecutor.Basic Mapping with Distributed HandlerIf you have an iterable (or iterables) that would result in less than hundreds of
thousands of tasks, it you can simply use the normalmapprovided by theDistributedHandler.client.Important Note:Notice, "... iterable that wouldresultin less than hundreds
of thousands of tasks...". This is important because what happens when you try tomapover a thousand image paths, each which spawns anAICSImageobject. Each one adds
thousands more tasks to the scheduler to complete. This will break and you should look
toLarge Iterable Batchinginstead.fromaics_dask_utilsimportDistributedHandler# `None` address provided means use local machine threadswithDistributedHandler(None)ashandler:futures=handler.client.map(lambdax:x+1,[1,2,3])results=handler.gather(futures)fromdistributedimportLocalClustercluster=LocalCluster()# Actual address provided means use the dask schedulerwithDistributedHandler(cluster.scheduler_address)ashandler:futures=handler.client.map(lambdax:x+1,[1,2,3])results=handler.gather(futures)Large Iterable BatchingIf you have an iterable (or iterables) that would result in more than hundreds of
thousands of tasks, you should usehandler.batched_mapto reduce the load on the
client. This will batch your requests rather than send than all at once.fromaics_dask_utilsimportDistributedHandler# `None` address provided means use local machine threadswithDistributedHandler(None)ashandler:results=handler.batched_map(lambdax:x+1,range(1e9)# 1 billion)fromdistributedimportLocalClustercluster=LocalCluster()# Actual address provided means use the dask schedulerwithDistributedHandler(cluster.scheduler_address)ashandler:results=handler.batched_map(lambdax:x+1,range(1e9)# 1 billion)Note:Notice that there is nohandler.gathercall afterbatched_map. This is
becausebatched_mapgathers results at the end of each batch rather than simply
returning their future's.InstallationStable Release:pip install aics_dask_utilsDevelopment Head:pip install git+https://github.com/AllenCellModeling/aics_dask_utils.gitDocumentationFor full package documentation please visitAllenCellModeling.github.io/aics_dask_utils.DevelopmentSeeCONTRIBUTING.mdfor information related to developing the code.Additional CommentsThis README, provided tooling, and documentation are not meant to be all encompassing
of the various operations you can do withdaskand other similar computing systems.
For further reading go todask.org.Free software: Allen Institute Software License