MCPcopy Create free account
hub / github.com/dask/dask / process_runnables

Function process_runnables

dask/order.py:298–404  ·  view source on GitHub ↗

Compute all currently runnable paths and either cache or execute them This is designed to ensure we are running tasks that are free to execute (e.g. the result of a splitter task) not too eagerly. If we executed such free tasks too early we'd be walking the graph in a too wi

()

Source from the content-addressed store, hash-verified

296
297 @_with_offset
298 def process_runnables() -> None:
299 """Compute all currently runnable paths and either cache or execute them
300
301 This is designed to ensure we are running tasks that are free to execute
302 (e.g. the result of a splitter task) not too eagerly. If we executed
303 such free tasks too early we'd be walking the graph in a too wide /
304 breadth first fashion that is not optimal. If instead we were to only
305 execute them once they are needed for a final result, this can cause
306 very high memory pressure since valuable reducers are executed too
307 late.
308
309 The strategy here is to take all runnable tasks and walk forwards until
310 we hit a reducer node (i.e. a node with more than one dependency). We
311 will remember/cache the path to this reducer node.
312 If this path leads to a leaf or if we find enough runnable paths for a
313 reducer to be runnable, we will execute the path.
314
315 If instead of a reducer a splitter is encountered that is runnable, we
316 will follow its splitter paths individually and apply the same logic to
317 each branch.
318 """
319 while runnable:
320 candidates = runnable.copy()
321 runnable.clear()
322 while candidates:
323 key = candidates.pop()
324 if key in runnable_hull or key in result:
325 continue
326 if key in leaf_nodes:
327 add_to_result(key)
328 continue
329 path = [key]
330 branches = deque([(0, path)])
331
332 while branches:
333 nsplits, path = branches.popleft()
334 while True:
335 # Loop invariant. Too expensive to compute at runtime
336 # assert not set(known_runnable_paths).intersection(runnable_hull)
337 current = path[-1]
338 runnable_hull.add(current)
339 deps_downstream = dependents[current]
340 deps_upstream = dependencies[current]
341 if not deps_downstream:
342 # FIXME: The fact that it is possible for
343 # num_needed[current] == 0 means we're doing some
344 # work twice
345 if num_needed[current] <= 1:
346 for k in path:
347 add_to_result(k)
348 else:
349 runnable_hull.discard(current)
350 elif len(path) == 1 or len(deps_upstream) == 1:
351 if len(deps_downstream) > 1:
352 nsplits += 1
353 for d in sorted(deps_downstream, key=sort_key):
354 # This ensures we're only considering splitters
355 # that are genuinely splitting and not

Callers 1

orderFunction · 0.85

Calls 5

add_to_resultFunction · 0.85
popMethod · 0.80
copyMethod · 0.45
clearMethod · 0.45
addMethod · 0.45

Tested by

no test coverage detected