Skip to content

Commit dec9ab9

Browse files
authored
Graph set_job_targets much faster, fix when targets change during traversal (#291)
for_all_nodes got a new option update_graph, which is True by default (old behavior), which can also be False to avoid updating the graph. set_job_targets is not really expected to update the graph. Not updating the graph makes it much faster. Fix #290
1 parent 6281c19 commit dec9ab9

1 file changed

Lines changed: 14 additions & 8 deletions

File tree

sisyphus/graph.py

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
from sisyphus.job_path import AbstractPath
55
from sisyphus.block import Block
66
import sisyphus.tools as tools
7-
import sisyphus.hash
87

98
import atexit
109
from inspect import isclass
@@ -502,7 +501,9 @@ def get_unfinished_jobs(job):
502501
self.for_all_nodes(get_unfinished_jobs, nodes=nodes)
503502
return states
504503

505-
def for_all_nodes(self, f, nodes=None, bottom_up=False, *, pool: Optional[ThreadPool] = None):
504+
def for_all_nodes(
505+
self, f, nodes=None, bottom_up=False, *, update_graph: bool = True, pool: Optional[ThreadPool] = None
506+
):
506507
"""
507508
Run function f for each node and ancestor for `nodes` from top down,
508509
stop expanding tree branch if functions returns False. Does not stop on None to allow functions with no
@@ -511,6 +512,8 @@ def for_all_nodes(self, f, nodes=None, bottom_up=False, *, pool: Optional[Thread
511512
:param (Job)->bool f: function will be executed for all nodes
512513
:param nodes: all nodes that will be checked, defaults to all output nodes in graph
513514
:param bool bottom_up: start with deepest nodes first, ignore return value of f
515+
:param update_graph: if True, update all nodes/jobs (calling :func:`Job._sis_runnable`)
516+
while running through the graph to get the most current dependency graph.
514517
:param pool: use custom thread pool
515518
:return: set with all visited nodes
516519
"""
@@ -523,7 +526,8 @@ def for_all_nodes(self, f, nodes=None, bottom_up=False, *, pool: Optional[Thread
523526
if path.creator:
524527
nodes.append(path.creator)
525528

526-
if gs.GRAPH_WORKER == 1:
529+
# with update_graph=False, it should be much faster to not use threading
530+
if gs.GRAPH_WORKER == 1 or not update_graph:
527531
visited_set = set()
528532
visited_list = []
529533
queue = list(reversed(nodes))
@@ -532,7 +536,8 @@ def for_all_nodes(self, f, nodes=None, bottom_up=False, *, pool: Optional[Thread
532536
if id(job) in visited_set:
533537
continue
534538
visited_set.add(id(job))
535-
job._sis_runnable()
539+
if update_graph:
540+
job._sis_runnable()
536541

537542
if bottom_up:
538543
# execute in reverse order at the end
@@ -583,8 +588,9 @@ def runner_helper(job):
583588
"""
584589
if stopped_event.is_set():
585590
return
586-
# make sure all inputs are updated
587-
job._sis_runnable()
591+
if update_graph:
592+
# make sure all inputs are updated
593+
job._sis_runnable()
588594
nonlocal finished
589595

590596
if bottom_up:
@@ -731,7 +737,7 @@ def f(job):
731737
except AttributeError:
732738
pass
733739

734-
self.for_all_nodes(f)
740+
self.for_all_nodes(f, update_graph=False)
735741

736742
for target in self.targets:
737743
if isinstance(target, OutputPath):
@@ -750,7 +756,7 @@ def f(job):
750756
return True
751757
return False
752758

753-
self.for_all_nodes(f=f, nodes=[out.creator])
759+
self.for_all_nodes(f=f, nodes=[out.creator], update_graph=False)
754760

755761

756762
def is_literal(obj, visited=None):

0 commit comments

Comments
 (0)