def optimize(self, graph: Graph): flag_changed = False """ Some operators does not support splitting, but only appear as constant. Workaround for such case, use ConstantFolding for limited operators even if it is turned off. """ cf = ConstantFolding() graph, flag_changed_in_cf = cf.optimize(graph, (Transpose, )) flag_changed |= flag_changed_in_cf c_before = traverse.filter_nodes(traverse.listup_variables(graph), ConstantVariable) c_size_before = sum([c.size for c in c_before]) for v in traverse.filter_nodes(traverse.listup_variables(graph), SplitTarget): axis = _choose_split_axis(v) _split_axis(v, axis, graph) flag_changed = True c_after = traverse.filter_nodes(traverse.listup_variables(graph), ConstantVariable) c_size_after = sum([c.size for c in c_after]) if c_size_before > c_size_after: raise Exception return graph, flag_changed
def allocate(graph: Graph) -> WebGLMemoryLayout: nodes = traverse.listup_nodes(graph) operators = traverse.filter_nodes(nodes, Operator) # type: List[Operator] variables = traverse.filter_nodes(nodes, Variable) # type: List[Variable] for i, v in enumerate(variables): if v.name is None: v.name = _name("v") dynamic_constants = traverse.filter_nodes([v for v in variables if not Placeholder.check_resolved(v.size)], ConstantVariable) assert len(dynamic_constants) == 0, f"ConstantVariable with unresolved placeholder shape is detected: f{dynamic_constants}" allocations = _get_allocations(graph, operators, variables) _optimize_buffer_reuse(allocations) variable_allocations = {v: allocations[v] for v in variables if not isinstance(v, ConstantVariable)} constant_allocations = {v: allocations[v] for v in variables if isinstance(v, ConstantVariable)} data = _update_constant_offset(constant_allocations) allocations = variable_allocations allocations.update(constant_allocations) layout = WebGLMemoryLayout(allocations, data) return layout
def allocate(graph: Graph) -> MemoryLayout: nodes = traverse.listup_nodes(graph) operators = traverse.filter_nodes(nodes, Operator) # type: List[Operator] variables = traverse.filter_nodes(nodes, Variable) # type: List[Variable] for i, v in enumerate(variables): if v.name is None: v.name = _name("v") dynamic_constants = traverse.filter_nodes([v for v in variables if not Placeholder.check_resolved(v.size)], ConstantVariable) assert len(dynamic_constants) == 0, f"ConstantVariable with unresolved placeholder shape is detected: f{dynamic_constants}" allocations = _get_allocations(graph, operators, variables) _optimize_inplace(operators, allocations) variable_allocations = {v: allocations[v] for v in variables if not isinstance(v, ConstantVariable)} constant_allocations = {v: allocations[v] for v in variables if isinstance(v, ConstantVariable)} _update_offset(variable_allocations) _optimize_buffer_reuse(variable_allocations) data = _update_constant_offset(constant_allocations) for allocation in set(variable_allocations.values()): allocation.offset += data.size allocations = variable_allocations allocations.update(constant_allocations) layout = MemoryLayout(allocations, data) if flags.VISUALIZE_MEMORY_ALLOCATION: _visualize_allocation(operators, variables, layout) return layout
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False ops = traverse.listup_operators(graph) ops = traverse.filter_nodes(ops, Inplace) ops = traverse.filter_nodes(ops, InlineInplace, mode_not=True) for op in ops: # type: Operator inplace = op.get_attribute(Inplace)[0] # type: Inplace if isinstance(op, Relu): op.attributes.add( InlineInplace(op, lambda exp: f"({exp}>0?{exp}:0)", inplace)) flag_changed = True elif isinstance(op, Elu): op.attributes.add( InlineInplace( op, lambda exp: f"({exp}>0?{exp}:(exp({exp})-1))", inplace)) flag_changed = True elif isinstance(op, Tanh): op.attributes.add( InlineInplace(op, lambda exp: f"(tanh({exp}))", inplace)) flag_changed = True else: continue return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op1 in traverse.filter_nodes(traverse.listup_operators(graph), Elementwise): # type: Elementwise if len(op1.inputs) <= 1: continue x0 = op1.inputs["x0"] x1 = op1.inputs["x1"] if isinstance(op1, ElementwiseAdd): op2 = x0.output_from op3 = x1.output_from if isinstance(op2, ElementwiseAdd) and isinstance( op3, ElementwiseAdd) and len(x0.input_to) == 1 and len( x1.input_to) == 1: # # x2 -+ # +-[op2: ElementwiseAdd]-> x0 -+ # x3 -+ | # +-[op1: ElementwiseAdd]-> y # x4 -+ | # +-[op3: ElementwiseAdd]-> x1 -+ # x5 -+ # x2 = op2.inputs["x0"] x3 = op2.inputs["x1"] x4 = op3.inputs["x0"] x5 = op3.inputs["x1"] cs = [] xs = [] for x in [x2, x3, x4, x5]: if isinstance(x, ConstantVariable): cs.append(x) else: xs.append(x) if len(cs) >= 2: y = op1.outputs["y"] y_new = cs[0] for c in cs[1:]: y_new = y_new + c for x in xs: y_new = y_new + x op1.remove_all() op2.remove_all() op3.remove_all() y.change_order(y_new.order) y_new.replace(y) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), self.pattern): flag_changed |= self.optimize_operator(graph, op) return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for concat in traverse.filter_nodes(traverse.listup_operators(graph), Concat): if len(concat.inputs) == 2: # Unrolling is not needed continue flag_changed = True xs = [concat.inputs[f"x{i}"] for i in range(len(concat.inputs))] y = concat.outputs["y"] concat.remove_all() while len(xs) > 1: hs = [] while len(xs) > 0: if len(xs) == 1: hs.append(xs.pop(0)) else: x0, x1 = xs.pop(0), xs.pop(0) h, = Concat(None, axis=concat.axis)(x0, x1) hs.append(h) xs = hs OptimizeRule.replace_variable(graph, y, xs[0].transpose_like(y)) return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Sgemm): # type: Sgemm A = op.inputs["A"] B = op.inputs["B"] M = op.M N = op.N K = op.K transpose_A = op.transpose_A transpose_B = op.transpose_B if transpose_A: if TextureShape.get(A) != [M, K]: flag_changed = True TextureShape.set(A, width=K, height=M) else: if TextureShape.get(A) != [K, M]: flag_changed = True TextureShape.set(A, width=M, height=K) if transpose_B: if TextureShape.get(B) != [K, N]: flag_changed = True TextureShape.set(B, width=N, height=K) else: if TextureShape.get(B) != [N, K]: flag_changed = True TextureShape.set(B, width=K, height=N) return graph, flag_changed
def generate(cls, graph: Graph, **kwargs): graph, _ = WebGLOptimizeRule().optimize(graph) if flags.DEBUG: traverse.dump(graph) with open("cg.dot", "w") as f: f.write(traverse.dump_dot(graph)) memory_layout = allocate(graph) constants_map = {} for constant in traverse.filter_nodes(traverse.listup_nodes(graph), ConstantVariable): # type: ConstantVariable constants_map[constant.name] = { "byte_offset": memory_layout[constant].offset * 4, "size": constant.size } constant_encoder = ConstantEncoder.get_encoder(kwargs.get("constant_encoder_name", None)) constants_bytes = constant_encoder.encode(memory_layout) kernels = cls.generate_kernels(graph) descriptor = GraphDescriptor( kernels=kernels, memory_layout=memory_layout, inputs=graph.inputs, outputs=graph.outputs, constants_encoding=constant_encoder.name, constants_map=constants_map, licenses=graph.licenses ) return GraphExecutionData(graph, descriptor, constants_bytes)
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes( traverse.listup_operators(graph), Deconvolution2D): # type: Deconvolution2D x = op.inputs["x"] w = op.inputs["w"] y = op.outputs["y"] flag_changed = True op.remove_all() a_filter, a_kh, a_kw = Axis(), Axis(), Axis() w, = ReinterpretAxis(None, in_order=OrderNHWC, out_order=Order( [Axis.C, a_kh, a_kw, a_filter]))(w) x, = ReinterpretAxis(None, in_order=OrderNHWC, out_order=Order( [Axis.N, Axis.H, Axis.W, a_filter]))(x) col, = Tensordot(None, axes=a_filter)(x, w) col = col.transpose( Order([Axis.N, Axis.H, Axis.W, a_kh, a_kw, Axis.C])) col = col.reshape(shape=[*col.shape[0:3], mul(col.shape[3:6])], order=OrderNHWC) new_y, = Col2Im(None, ksize=op.ksize, stride=op.stride, padding=op.padding)(col) OptimizeRule.replace_variable(graph, new_y.transpose_like(y), y) return graph, flag_changed
def allocate_variables(cls, graph: Graph, variables: List[Variable]): # check if constant variable with shape with unresolved placeholder. dynamic_constants = traverse.filter_nodes( [v for v in variables if not Placeholder.check_resolved(v.size)], ConstantVariable) assert len( dynamic_constants ) == 0, f"ConstantVariable with unresolved placeholder shape is detected: f{dynamic_constants}" ops = traverse.listup_operators(graph) layout = MemoryLayout() lifetime = get_lifetime( graph, ops, variables) # type: Dict[Variable, Tuple[int, int]] offsets = generate_allocation_info( variables, lifetime) # type: Dict[Variable, Union[int, Placeholder]] for variable, offset in offsets.items(): layout.append(variable, offset) layout.data = np.zeros(layout.static_size, dtype=np.float32) constant_size = 0 for var in variables: if not isinstance(var, ConstantVariable): continue allocation = layout[var] layout.data[allocation.offset:allocation.offset + allocation.size] = var.data.flatten() constant_size += var.data.size layout.data = layout.data[:constant_size] if flags.VISUALIZE_MEMORY_ALLOCATION: _visualize_allocation(ops, variables, layout, lifetime, offsets) return layout
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Linear): x = op.inputs["x"] w = op.inputs["w"] y = op.outputs["y"] flag_changed = True op.remove_all() a_filter = Axis() if x.ndim == 2: w, = ReinterpretAxis(None, in_order=OrderNC, out_order=Order([Axis.C, a_filter]))(w) new_y, = Tensordot(None, axes=[Axis.C, a_filter])(x, w) elif x.ndim == 4: w, = ReinterpretAxis( None, in_order=OrderNHWC, out_order=Order([Axis.C, Axis.H, Axis.W, a_filter]))(w) new_y, = Tensordot(None, axes=[[Axis.H, Axis.W, Axis.C], [Axis.H, Axis.W, a_filter]])(x, w) else: raise NotImplementedError OptimizeRule.replace_variable(graph, new_y.transpose_like(y), y) return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), InplaceOperator): attr = op.get_attribute(InplaceOperator)[0] v_in = attr.get_input() v_out = attr.get_output() flag_inplace = True if v_in.has_attribute(Input): # Input variable cannot be overwritten. flag_inplace = False if isinstance(v_in, ConstantVariable): # Constant variable cannot be overwritten flag_inplace = False if any(v_in.stride_dict[a] != v_out.stride_dict[a] for a in v_out.order.axes if a in v_in.order.axes): flag_inplace = False if flag_inplace != attr.get_status(): attr.toggle_status(flag_inplace) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Linear): # type: Linear x = op.inputs["x"] w = op.inputs["w"] y = op.outputs["y"] assert x.order == OrderNC or x.order == OrderNHWC, f"(x.order) = {x.order}" assert w.order == OrderCN or w.order == OrderHWCN, f"(x.order) = {w.order}" assert y.order == OrderNC or y.order == OrderNHWC, f"(x.order) = {y.order}" assert w.ndim == x.ndim flag_changed = True op.remove_all() sgemm = Sgemm(None, M=y.shape_dict[Axis.N], N=y.size // y.shape_dict[Axis.N], K=x.size // x.shape_dict[Axis.N], out_shape=y.shape, out_order=y.order, transpose_A=True, transpose_B=True) new_y, = sgemm(x, w) sgemm.replace_output(new_y, y) return graph, flag_changed
def generate(cls, graph: Graph, **kwargs): data_dict = {} # type: Dict[int, Tuple[GraphDescriptor, bytes]] for max_texture_size in [4096, 8192, 16384]: config.WEBGL_MAX_TEXTURE_SIZE = max_texture_size graph, _ = WebGLOptimizeRule().optimize(graph) memory_layout = allocate(graph) constants_map = {} for constant in traverse.filter_nodes(traverse.listup_nodes(graph), ConstantVariable): # type: ConstantVariable constants_map[constant.name] = { "byte_offset": memory_layout[constant].offset * 4, "size": constant.size } constant_encoder = ConstantEncoder.get_encoder(kwargs.get("constant_encoder_name", None)) constants_bytes = constant_encoder.encode(memory_layout) kernels = cls.generate_kernels(graph) descriptor = GraphDescriptor( kernels=kernels, memory_layout=memory_layout, inputs=graph.inputs, outputs=graph.outputs, constants_encoding=constant_encoder.name, constants_map=constants_map, licenses=graph.licenses ) data_dict[max_texture_size] = (descriptor, constants_bytes) return GraphExecutionData(graph, data_dict)
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Convolution2D): # type: Convolution2D x = op.inputs["x"] w = op.inputs["w"] y = op.outputs["y"] flag_changed = True op.remove_all() a_filter, a_kh, a_kw = Axis(), Axis(), Axis() w, = ReinterpretAxis(None, in_order=OrderNHWC, out_order=Order( [Axis.C, a_kh, a_kw, a_filter]))(w) if op.WH == 1 and op.WW == 1 and op.stride == ( 1, 1) and op.padding == (0, 0): # Projection col, = ReinterpretAxis( None, in_order=OrderNHWC, out_order=Order([Axis.N, Axis.H, Axis.W, a_filter]))(x) new_y, = Tensordot(None, [[a_filter], [a_kh, a_kw, a_filter]])(col, w) elif op.WH == x.shape_dict[Axis.H] and op.WW == x.shape_dict[ Axis.W] and op.padding == (0, 0): # Global convolution col, = ReinterpretAxis(None, in_order=OrderNHWC, out_order=Order( [Axis.N, a_kh, a_kw, a_filter]))(x) new_y, = Tensordot( None, [[[a_kh, a_kw, a_filter], [a_kh, a_kw, a_filter]], [a_kh, a_kw, a_filter]])(col, w) else: # General convolution col, = Im2Col(None, ksize=op.ksize, stride=op.stride, padding=op.padding, dilation_rate=op.dilation_rate)(x) col, = ReinterpretAxis( None, in_order=OrderNHWC, out_order=Order([Axis.N, Axis.H, Axis.W, a_filter]))(col) new_y, = Tensordot(None, [[a_filter], [a_kh, a_kw, a_filter]])(col, w) new_y = new_y.transpose(y.order) OptimizeRule.replace_variable(graph, new_y, y) return graph, flag_changed
def _get_allocations(graph: Graph, operators: List[Operator], variables: List[Variable]) -> AllocationDict: T_LAST = len(operators) allocations = {} # type: AllocationDict retain_count = {v: 0 for v in variables} # type: Dict[Variable, int] allocated = set() # type: Set[Variable] for v in traverse.filter_nodes(variables, ConstantVariable): # type: ConstantVariable # Constant variable cannot be released allocations[v] = Allocation(size=v.size, begin=0, end=T_LAST) allocated.add(v) for v in graph.inputs: # Input variable cannot be released allocations[v] = Allocation(size=v.size, begin=0, end=T_LAST) allocated.add(v) for v in graph.outputs: # Output variable cannot be released, but it's not needed to be allocated from the begin allocations[v] = Allocation(size=v.size, begin=_T_UNKNOWN, end=T_LAST) allocated.add(v) for t, op in enumerate(operators): for v in op.outputs.values(): if v in allocated: # Allocation object is already created (output variable, etc.) if allocations[v].begin == _T_UNKNOWN: allocations[v].begin = t else: # Create new allocation object allocations[v] = Allocation(size=v.size, begin=t, end=_T_UNKNOWN) retain_count[v] = len(v.input_to) allocated.add(v) for v in op.inputs.values(): if v not in allocated: # Allocate allocations[v] = Allocation(size=v.size, begin=t, end=_T_UNKNOWN) retain_count[v] = len(v.input_to) allocated.add(v) if allocations[v].end != _T_UNKNOWN: # Release timing is already determined (input, output, or constant variable). continue # Release input variable retain_count[v] -= 1 if retain_count[v] == 0: # `t + 1` means that `v` will be released *AFTER* `op` will be finished. allocations[v].end = t + 1 for a in allocations.values(): if a.begin == _T_UNKNOWN: a.begin = 0 if a.end == _T_UNKNOWN: a.end = T_LAST return allocations
def test_filter_nodes(): global graph, op1 op1.attributes.add(TestAttribute(op1)) op2.attributes.add(TestAttribute(op2)) ops = filter_nodes([op1, op2, op3], TestAttribute) assert tuple(ops) == (op1, op2)
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op1 in traverse.filter_nodes(traverse.listup_operators(graph), Associative): # type: Operator associative1 = op1.get_attribute(Associative)[0] var1, var2 = associative1.vars op2 = var1.output_from if isinstance(var1, ConstantVariable): # Left hand operand(var1) has no child tree continue if var1 in graph.outputs or len(var1.input_to) > 1: # var1 will be removed in this optimize rule continue if not isinstance(op2, op1.__class__): # op1 and op2 must be same operator class continue associative2 = op2.get_attribute(Associative)[0] var3, var4 = associative2.vars if not isinstance(var4, ConstantVariable): # No optimization is needed. # If either var3 or var4 is constant, then it is var4 because optimization rule of commutative operator reorder operands to # gather constant variables for right hand. continue """ var3 -+ +-{op2}- var1 -+ var4 -+ +-{op1}- var2 -+ """ if isinstance(var2, ConstantVariable): # Fold var4 and var2 associative1.reorder( op2) # (var3*var4)*var2 => var3*(var4*var2) flag_changed = True else: # Sweep out var4 if not op1.has_attribute(Commutative): continue associative2 = op2.get_attribute(Associative)[0] commutative2 = op2.get_attribute(Commutative)[0] if not isinstance(associative2.vars[1], ConstantVariable): continue commutative2.swap() # (var3*var4)*var2 => (var4*var3)*var2 associative1.reorder( op2) # (var4*var3)*var2 => var4*(var3*var2) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Convolution2D): # type: Convolution2D x = op.inputs["x"] w = op.inputs["w"] # type: ConstantVariable old_y = op.outputs["y"] flag_changed = True op.remove_all() assert x.order == OrderNHWC assert isinstance(w, ConstantVariable) assert old_y.order == OrderNHWC w.change_order(OrderNHWC) col, = Im2Col(None, ksize=op.ksize, stride=op.stride, padding=op.padding, dilation_rate=op.dilation_rate)(x) col.change_order(OrderNHWC) ChannelMode.set_mode(col, ChannelModeEnum.RGBA) M = col.shape_dict[Axis.N] * col.shape_dict[ Axis.H] * col.shape_dict[Axis.W] N = w.shape_dict[Axis.N] K = col.shape_dict[Axis.C] if K > (w.size // N): w2_data = np.hstack([ w.data.reshape(N, w.size // N), np.zeros([N, K - w.size // N]) ]) else: w2_data = w.data.reshape(N, w.size // N) w = ConstantVariable(w2_data, OrderNC) ChannelMode.set_mode(w, ChannelModeEnum.RGBA) sgemm = Sgemm(None, M=M, N=N, K=K, out_shape=[ col.shape_dict[Axis.N], col.shape_dict[Axis.H], col.shape_dict[Axis.W], w.shape_dict[Axis.N] ], out_order=OrderNHWC, transpose_A=True, transpose_B=False) new_y, = sgemm(col, w) sgemm.replace_output(new_y, old_y) return graph, flag_changed
def optimize(self, graph: Graph): flag_changed = False for v in traverse.filter_nodes(traverse.listup_nodes(graph), SplitTarget): # type: Variable axis = _choose_split_axis(v) _split_axis(v, axis, graph) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Tensordot): if not op.has_attribute(UseEigenAttribute): op.attributes.add(UseEigenAttribute()) flag_changed = True graph.licenses["eigen"] = EIGEN_LICENSE return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: if not (flags.optimize.OPTIMIZE and flags.optimize.CONCAT_SCALAR_OPERATION): return graph, False flag_changed = False nodes = traverse.listup_nodes(graph) filtered_nodes = traverse.filter_nodes( nodes, ScalarAffine) # type: List[ScalarAffine] while len(filtered_nodes) > 0: op = filtered_nodes.pop() if op.scale == 1 and op.bias == 0: remove_operator(op) flag_changed = True filtered_nodes = traverse.filter_nodes( nodes, ScalarAdd) # type: List[ScalarAdd] while len(filtered_nodes) > 0: op = filtered_nodes.pop() if op.value == 0: remove_operator(op) flag_changed = True filtered_nodes = traverse.filter_nodes( nodes, ScalarMul) # type: List[ScalarMul] while len(filtered_nodes) > 0: op = filtered_nodes.pop() if op.value == 1: remove_operator(op) flag_changed = True filtered_nodes = traverse.filter_nodes( nodes, ScalarPow) # type: List[ScalarPow] while len(filtered_nodes) > 0: op = filtered_nodes.pop() if op.value == 1: remove_operator(op) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), Sgemm): # type: Sgemm if not op.has_attribute(SgemmWithEigen): op.attributes.add(SgemmWithEigen(op)) flag_changed = True graph.licenses["eigen"] = EIGEN_LICENSE return graph, flag_changed
def optimize(self, graph: Graph): flag_changed = False c_before = traverse.filter_nodes(traverse.listup_variables(graph), ConstantVariable) c_size_before = sum([c.size for c in c_before]) for v in traverse.filter_nodes(traverse.listup_variables(graph), SplitTarget): axis = _choose_split_axis(v) _split_axis(v, axis, graph) flag_changed = True c_after = traverse.filter_nodes(traverse.listup_variables(graph), ConstantVariable) c_size_after = sum([c.size for c in c_after]) if c_size_before > c_size_after: raise Exception return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False # replace AxiswiseBias by ElementwiseAdd flag_warn = True for op in traverse.filter_nodes(traverse.listup_operators(graph), AxiswiseBias): # type: AxiswiseBias flag_changed = True x = op.inputs["x0"] b = op.inputs["x1"] y = op.outputs["y"] op.remove_all() OptimizeRule.replace_variable(graph, (x + b).change_order(y.order), y) if flag_warn: flag_warn = False console.warning( "AxiswiseBias will be removed in the future version. Use ElementwiseAdd.", DeprecationWarning) # replace AxiswiseScale by ElementwiseMul flag_warn = True for op in traverse.filter_nodes(traverse.listup_operators(graph), AxiswiseScale): # type: AxiswiseScale flag_changed = True x = op.inputs["x0"] s = op.inputs["x1"] y = op.outputs["y"] op.remove_all() OptimizeRule.replace_variable(graph, (x * s).change_order(y.order), y) if flag_warn: flag_warn = False console.warning( "AxiswiseScale will be removed in the future version. Use ElementwiseMul.", DeprecationWarning) return graph, flag_changed
def allocate(cls, graph: Graph) -> Tuple[MemoryLayout, MemoryLayout, np.array]: variables = set(traverse.listup_variables(graph)) constants = set(traverse.filter_nodes( variables, Constant)) # type: Set[ConstantVariable] variables = variables.difference(constants) variables = list(variables) constants = list(constants) constants_layout, data = cls.allocate_constants(constants) variables_layout = cls.allocate_variables(graph, variables) return variables_layout, constants_layout, data
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False ops = traverse.listup_operators(graph) ops = traverse.filter_nodes(ops, PostInlineInplace, mode_not=True) for op in ops: # type: Operator if isinstance(op, Sgemm): op.attributes.add(PostInlineInplace(op)) flag_changed = True else: continue return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for op in traverse.filter_nodes(traverse.listup_operators(graph), ScalarAffine): # type: ScalarAffine x = op.inputs["x0"] y = op.outputs["y"] op.remove_all() y_dummy = x * op.scale + op.bias # type: Variable y_dummy.change_order(y.order) y_dummy.replace(y) flag_changed = True return graph, flag_changed
def optimize(self, graph: Graph) -> Tuple[Graph, bool]: flag_changed = False for concat in traverse.filter_nodes(traverse.listup_operators(graph), Concat): # type: Concat if concat.has_attribute(ConcatWorkspaceAttached): attr = concat.get_attribute(ConcatWorkspaceAttached)[0] else: flag_changed = True attr = ConcatWorkspaceAttached(concat) concat.attributes.add(attr) flag_changed |= attr.update() return graph, flag_changed