def generate_graph(self, filename=None, write_on_disk=True, with_data_links=False, background="transparent", quiet=False): """Produces a Graphviz PNG image of the unit control flow. Returns the DOT graph description (string). If write_on_disk is False, filename is ignored. If filename is None, a temporary file name is taken. """ g = pydot.Dot(graph_name="Workflow", graph_type="digraph", bgcolor=background, mindist=0.5, overlap="false", outputorder="edgesfirst") g.set_prog("circo") visited_units = set() boilerplate = {self.start_point} while len(boilerplate) > 0: unit = boilerplate.pop() visited_units.add(unit) node = pydot.Node(hex(id(unit))) unit_file_name = os.path.relpath(inspect.getfile(unit.__class__), root.common.dirs.veles) if six.PY2 and unit_file_name.endswith('.pyc'): unit_file_name = unit_file_name[:-1] node.set("label", '<<b><font point-size=\"18\">%s</font></b><br/>' '<font point-size=\"14\">%s</font>>' % (unit.name, unit_file_name)) node.set("shape", "rect") node.add_style("rounded") node.add_style("filled") color = Workflow.VIEW_GROUP_COLORS.get(unit.view_group, "white") node.set("fillcolor", color) node.set("gradientangle", "90") if isinstance(unit, Repeater): g.set("root", hex(id(unit))) g.add_node(node) for link in self._iter_links(unit.links_to): src_id = hex(id(unit)) dst_id = hex(id(link)) if unit.view_group == link.view_group and \ unit.view_group in self.VIP_GROUPS: # Force units of the same group to be sequential for _ in range(2): g.add_edge(pydot.Edge( src_id, dst_id, color="#ffffff00")) g.add_edge(pydot.Edge(src_id, dst_id, penwidth=3, weight=100)) if link not in visited_units and link not in boilerplate: boilerplate.add(link) if with_data_links: # Add data links # Circo does not allow to ignore certain edges, so we need to save # the intermediate result (_, dotfile) = tempfile.mkstemp(".dot", "workflow_") g.write(dotfile, format='dot') g = pydot.graph_from_dot_file(dotfile) os.remove(dotfile) # Neato without changing the layout g.set_prog("neato -n") attrs = defaultdict(list) refs = [] for unit in self: for key, val in unit.__dict__.items(): if key.startswith('__') and hasattr(unit, key[2:]) and \ LinkableAttribute.__is_reference__(val): refs.append((unit, key[2:]) + val) if (val is not None and not Unit.is_immutable(val) and key not in Workflow.HIDDEN_UNIT_ATTRS and not key.endswith('_') and self.filter_unit_graph_attrs(val)): try: if key[0] == '_' and hasattr(unit, key[1:]): key = key[1:] except AssertionError: key = key[1:] attrs[id(val)].append((unit, key)) for ref in refs: g.add_edge(pydot.Edge( hex(id(ref[0])), hex(id(ref[2])), constraint="false", label=('"%s"' % ref[1]) if ref[1] == ref[3] else '"%s -> %s"' % (ref[1], ref[3]), fontcolor='gray', fontsize="8.0", color='gray')) for vals in attrs.values(): if len(vals) > 1: for val1 in vals: for val2 in vals: if val1[0] == val2[0]: continue label = ('"%s"' % val1[1]) if val1[1] == val2[1] \ else '"%s:%s"' % (val1[1], val2[1]) g.add_edge(pydot.Edge( hex(id(val1[0])), hex(id(val2[0])), weight=0, label=label, dir="both", color='gray', fontcolor='gray', fontsize="8.0", constraint="false")) if write_on_disk: if not filename: try: os.mkdir(os.path.join(root.common.dirs.cache, "plots"), mode=0o775) except FileExistsError: pass (_, filename) = tempfile.mkstemp( os.path.splitext(filename)[1], "workflow_", dir=os.path.join(root.common.dirs.cache, "plots")) if not quiet: self.debug("Saving the workflow graph to %s", filename) try: g.write(filename, format=os.path.splitext(filename)[1][1:]) except pydot.InvocationException as e: if "has no position" not in e.value: raise from_none(e) error_marker = "Error: node " hex_pos = e.value.find(error_marker) + len(error_marker) buggy_id = e.value[hex_pos:hex_pos + len(hex(id(self)))] buggy_unit = next(u for u in self if hex(id(u)) == buggy_id) self.warning("Looks like %s is not properly linked, unable to " "draw the data links.", buggy_unit) return self.generate_graph(filename, write_on_disk, False, background) if not quiet: self.info("Saved the workflow graph to %s", filename) desc = g.to_string().strip() if not quiet: self.debug("Graphviz workflow scheme:\n%s", desc) return desc, filename
def main(): def nothing(): pass def clBLASOff(): logging.info("\nclBLAS = OFF\n") root.common.engine.ocl.clBLAS = False def clBLASOn(): logging.info("\nclBLAS = ON\n") root.common.engine.ocl.clBLAS = True for backend in ( (CUDADevice, nothing), (OpenCLDevice, clBLASOff), (OpenCLDevice, clBLASOn), ): device_class = backend[0] backend[1]() for dtype in ( "float", "double", ): logging.info("\n%s: benchmark started for dtype %s\n", device_class, dtype) root.common.precision_type = dtype root.common.precision_level = 0 try: device = device_class() except Exception as e: logging.error("Could not create %s: %s", device_class, e) break launcher = DummyLauncher() wf = BenchmarkWorkflow(launcher, loader_name="imagenet_loader", decision_config=root.decision, layers=root.alexnet.layers, loss_function="softmax") wf.initialize(device, snapshot=False) if device_class is CUDADevice: wf.generate_graph("alexnet.svg") wf.run() logging.info( "Forward pass: %.2f msec", 1000.0 * (wf.t1.times[-1] - wf.t1.times[1]) / (wf.t1.n_it - 1)) logging.info( "Backward pass: %.2f msec", 1000.0 * (wf.t3.times[-1] - wf.t3.times[1]) / (wf.t3.n_it - 1)) logging.info("\n%s: benchmark ended for dtype %s\n", device_class, dtype) # Full garbage collection del wf del launcher del device pool = Unit.reset_thread_pool() gc.collect() pool.shutdown() del pool gc.collect() # For pypy which can garbage colect with delay for _ in range(100): gc.collect() logging.info("End of job")
def generate_graph(self, filename=None, write_on_disk=True, with_data_links=False, background="transparent", quiet=False): """Produces a Graphviz PNG image of the unit control flow. Returns the DOT graph description (string). If write_on_disk is False, filename is ignored. If filename is None, a temporary file name is taken. """ g = pydot.Dot(graph_name="Workflow", graph_type="digraph", bgcolor=background, mindist=0.5, overlap="false", outputorder="edgesfirst") g.set_prog("circo") visited_units = set() boilerplate = {self.start_point} while len(boilerplate) > 0: unit = boilerplate.pop() visited_units.add(unit) node = pydot.Node(hex(id(unit))) unit_file_name = os.path.relpath(inspect.getfile(unit.__class__), root.common.dirs.veles) if six.PY2 and unit_file_name.endswith('.pyc'): unit_file_name = unit_file_name[:-1] node.set( "label", '<<b><font point-size=\"18\">%s</font></b><br/>' '<font point-size=\"14\">%s</font>>' % (unit.name, unit_file_name)) node.set("shape", "rect") node.add_style("rounded") node.add_style("filled") color = Workflow.VIEW_GROUP_COLORS.get(unit.view_group, "white") node.set("fillcolor", color) node.set("gradientangle", "90") if isinstance(unit, Repeater): g.set("root", hex(id(unit))) g.add_node(node) for link in self._iter_links(unit.links_to): src_id = hex(id(unit)) dst_id = hex(id(link)) if unit.view_group == link.view_group and \ unit.view_group in self.VIP_GROUPS: # Force units of the same group to be sequential for _ in range(2): g.add_edge( pydot.Edge(src_id, dst_id, color="#ffffff00")) g.add_edge(pydot.Edge(src_id, dst_id, penwidth=3, weight=100)) if link not in visited_units and link not in boilerplate: boilerplate.add(link) if with_data_links: # Add data links # Circo does not allow to ignore certain edges, so we need to save # the intermediate result (_, dotfile) = tempfile.mkstemp(".dot", "workflow_") g.write(dotfile, format='dot') g = pydot.graph_from_dot_file(dotfile) os.remove(dotfile) # Neato without changing the layout g.set_prog("neato -n") attrs = defaultdict(list) refs = [] for unit in self: for key, val in unit.__dict__.items(): if key.startswith('__') and hasattr(unit, key[2:]) and \ LinkableAttribute.__is_reference__(val): refs.append((unit, key[2:]) + val) if (val is not None and not Unit.is_immutable(val) and key not in Workflow.HIDDEN_UNIT_ATTRS and not key.endswith('_') and self.filter_unit_graph_attrs(val)): try: if key[0] == '_' and hasattr(unit, key[1:]): key = key[1:] except AssertionError: key = key[1:] attrs[id(val)].append((unit, key)) for ref in refs: g.add_edge( pydot.Edge(hex(id(ref[0])), hex(id(ref[2])), constraint="false", label=('"%s"' % ref[1]) if ref[1] == ref[3] else '"%s -> %s"' % (ref[1], ref[3]), fontcolor='gray', fontsize="8.0", color='gray')) for vals in attrs.values(): if len(vals) > 1: for val1 in vals: for val2 in vals: if val1[0] == val2[0]: continue label = ('"%s"' % val1[1]) if val1[1] == val2[1] \ else '"%s:%s"' % (val1[1], val2[1]) g.add_edge( pydot.Edge(hex(id(val1[0])), hex(id(val2[0])), weight=0, label=label, dir="both", color='gray', fontcolor='gray', fontsize="8.0", constraint="false")) if write_on_disk: if not filename: try: os.mkdir(os.path.join(root.common.dirs.cache, "plots"), mode=0o775) except FileExistsError: pass (_, filename) = tempfile.mkstemp(os.path.splitext(filename)[1], "workflow_", dir=os.path.join( root.common.dirs.cache, "plots")) if not quiet: self.debug("Saving the workflow graph to %s", filename) try: g.write(filename, format=os.path.splitext(filename)[1][1:]) except pydot.InvocationException as e: if "has no position" not in e.value: raise from_none(e) error_marker = "Error: node " hex_pos = e.value.find(error_marker) + len(error_marker) buggy_id = e.value[hex_pos:hex_pos + len(hex(id(self)))] buggy_unit = next(u for u in self if hex(id(u)) == buggy_id) self.warning( "Looks like %s is not properly linked, unable to " "draw the data links.", buggy_unit) return self.generate_graph(filename, write_on_disk, False, background) if not quiet: self.info("Saved the workflow graph to %s", filename) desc = g.to_string().strip() if not quiet: self.debug("Graphviz workflow scheme:\n%s", desc) return desc, filename
def main(): def nothing(): pass def clBLASOff(): logging.info("\nclBLAS = OFF\n") root.common.engine.ocl.clBLAS = False def clBLASOn(): logging.info("\nclBLAS = ON\n") root.common.engine.ocl.clBLAS = True for backend in ((CUDADevice, nothing), (OpenCLDevice, clBLASOff), (OpenCLDevice, clBLASOn), ): device_class = backend[0] backend[1]() for dtype in ("float", "double", ): logging.info("\n%s: benchmark started for dtype %s\n", device_class, dtype) root.common.precision_type = dtype root.common.precision_level = 0 try: device = device_class() except Exception as e: logging.error("Could not create %s: %s", device_class, e) break launcher = DummyLauncher() wf = BenchmarkWorkflow(launcher, loader_name="imagenet_loader", decision_config=root.decision, layers=root.alexnet.layers, loss_function="softmax") wf.initialize(device, snapshot=False) if device_class is CUDADevice: wf.generate_graph("alexnet.svg") wf.run() logging.info("Forward pass: %.2f msec", 1000.0 * (wf.t1.times[-1] - wf.t1.times[1]) / (wf.t1.n_it - 1)) logging.info("Backward pass: %.2f msec", 1000.0 * (wf.t3.times[-1] - wf.t3.times[1]) / (wf.t3.n_it - 1)) logging.info("\n%s: benchmark ended for dtype %s\n", device_class, dtype) # Full garbage collection del wf del launcher del device pool = Unit.reset_thread_pool() gc.collect() pool.shutdown() del pool gc.collect() # For pypy which can garbage colect with delay for _ in range(100): gc.collect() logging.info("End of job")