TrainingExtensions/torch/src/python/aimet_torch/meta/connectedgraph.py
def _insert_split_op_in_connected_graph(self, preceding_op: Op, split_op: Op):
        """
        Insert a Split Op below the preceding Op in the connected graph.
        :param preceding_op: Op prior to split op
        :param split_op: Split op to insert
        """

        # Important Notes
        # Op:
        # An Op class represents a module in a model.
        #
        # Product:
        # In this version of the Winnower, the Product class represents the following entities in a model.
        # 1) a Tensor between two modules (in Winnower, 2 Ops).
        # 2) an input
        # 3) a constant
        # 4) a parameter
        #
        # Considering only the definition #1) above, i.e., Product is a Tensor between 2 Ops,
        # an Op's inputs and output are Products.
        # That means, an Op could have multiple input Products and one output Product.
        # Examples of Op with multiple input products: add, cat (Concat)
        # A Product's Producer and Consumer are Ops.
        # A Product could have only one Producer but could have multiple consumers.
        # For example, a Split Op has one output.  The Split Op's single output isa Product.
        # That product's single Producer is the Split Op and multiple consumers are the 2 Ops in the 2 branches of
        # the Split, that receive the Split output.

        # Steps:
        # 1. Create a new Product for Split Op's output.
        # 2.This product has multiple consumers. Add the consumers to the Product.
        #   Get the consumers from the op's multiple products.
        # 3. Set the the current Op's output Product's consumer to Split Op. The output product's name must be changed.
        # 4. Set the Split Op's input to point to current Op's output. Its name must be changed.

        # 1. Create a new Product for Split Op's output.
        split_op_product = self._create_split_op_output_product(preceding_op, split_op)
        split_op.output = split_op_product

        # 2.This product has multiple consumers. Add the consumers to the Product.
        # Get the consumers from the op's multiple products.

        self._add_consumers_to_split_op_product(preceding_op, split_op_product)

        # 3. Create a new product to connect the preceding Op to the Split Op.
        # Set the the preceding Op's output Product's consumer to Split Op.

        # The preceding Op's output products (products, since it was behaving like a Split) are going to be deleted,
        # since a Split is being inserted in the connected graph.
        # Save the preceding Op's output Product shape.
        # This is needed to create the new product from the preceding Op to the newly being inserted Split Op.
        new_product_shape = preceding_op.output.shape

        # Since the preceding Op was behaving like a Split Op, it  would have 2 products with the preceding Op as the
        # producer. Delete these products from the product dictionary.
        preceding_op_product_names = self.get_product_names_from_dotted_name(preceding_op.dotted_name)
        for name in preceding_op_product_names:
            # Important Notes
            # The following check is needed since ResNet uses the same Relu twice in BasicBlock's forward()
            # Please read the details comments in _add_consumers_to_split_op_product()
            if preceding_op.name in name:
                deleted_product = self._products.pop(name)
                logger.debug("Insert Split Op: Step 3. Deleted product: %s", deleted_product)

        new_product_name = preceding_op.name + '__to__' + split_op.name
        new_product_shape = preceding_op.output.shape
        new_product = self._add_product(new_product_name, new_product_shape)
        new_product.producer = preceding_op
        preceding_op.output = new_product
        preceding_op.output.consumers.append(split_op)

        # 4. Set the Split Op's input to point to current Op's output.
        # new_name = preceding_op.name + '__to__' + split_op.name
        split_op.inputs.append(preceding_op.output)

        Insert a Split Op below the preceding Op in the connected graph.
        :param preceding_op: Op prior to split op
        :param split_op: Split op to insert
        
Insert a Split Op below the preceding Op in the connected graph.
Insert a Split Op below the preceding Op in the connected graph .
def _insert_split_op_in_connected_graph(self, preceding_op: Op, split_op: Op):
         Product:
         In this version of the Winnower, the Product class represents the following entities in a model.
         1) a Tensor between two modules (in Winnower, 2 Ops).
         2) an input
         3) a constant
         4) a parameter
         Considering only the definition 1) above, i.e., Product is a Tensor between 2 Ops,
         an Op's inputs and output are Products.
         That means, an Op could have multiple input Products and one output Product.
         Examples of Op with multiple input products: add, cat (Concat)
         A Product's Producer and Consumer are Ops.
         A Product could have only one Producer but could have multiple consumers.
         For example, a Split Op has one output.  The Split Op's single output isa Product.
         That product's single Producer is the Split Op and multiple consumers are the 2 Ops in the 2 branches of
         the Split, that receive the Split output.
         Steps:
         1. Create a new Product for Split Op's output.
         2.This product has multiple consumers. Add the consumers to the Product.
           Get the consumers from the op's multiple products.
         3. Set the the current Op's output Product's consumer to Split Op. The output product's name must be changed.
         4. Set the Split Op's input to point to current Op's output. Its name must be changed.
         1. Create a new Product for Split Op's output.
        split_op_product = self._create_split_op_output_product(preceding_op, split_op)
        split_op.output = split_op_product
         2.This product has multiple consumers. Add the consumers to the Product.
         Get the consumers from the op's multiple products.
        self._add_consumers_to_split_op_product(preceding_op, split_op_product)
         3. Create a new product to connect the preceding Op to the Split Op.
         Set the the preceding Op's output Product's consumer to Split Op.
         The preceding Op's output products (products, since it was behaving like a Split) are going to be deleted,
         since a Split is being inserted in the connected graph.
         Save the preceding Op's output Product shape.
         This is needed to create the new product from the preceding Op to the newly being inserted Split Op.
        new_product_shape = preceding_op.output.shape
         Since the preceding Op was behaving like a Split Op, it  would have 2 products with the preceding Op as the
         producer. Delete these products from the product dictionary.
        preceding_op_product_names = self.get_product_names_from_dotted_name(preceding_op.dotted_name)
        for name in preceding_op_product_names:
             The following check is needed since ResNet uses the same Relu twice in BasicBlock's forward()
             Please read the details comments in _add_consumers_to_split_op_product()
            if preceding_op.name in name:
                deleted_product = self._products.pop(name)
                logger.debug("Insert Split Op: Step 3. Deleted product: %s", deleted_product)
        new_product_name = preceding_op.name + '__to__' + split_op.name
        new_product_shape = preceding_op.output.shape
        new_product = self._add_product(new_product_name, new_product_shape)
        new_product.producer = preceding_op
        preceding_op.output = new_product
        preceding_op.output.consumers.append(split_op)
         4. Set the Split Op's input to point to current Op's output.
         new_name = preceding_op.name + '__to__' + split_op.name
        split_op.inputs.append(preceding_op.output)
def _insert_split_op_in_connected_graph ( self , preceding_op : Op , split_op : Op ) : split_op_product = self . _create_split_op_output_product ( preceding_op , split_op ) split_op . output = split_op_product self . _add_consumers_to_split_op_product ( preceding_op , split_op_product ) new_product_shape = preceding_op . output . shape preceding_op_product_names = self . get_product_names_from_dotted_name ( preceding_op . dotted_name ) for name in preceding_op_product_names : if preceding_op . name in name : deleted_product = self . _products . pop ( name ) logger . debug ( "Insert Split Op: Step 3. Deleted product: %s" , deleted_product ) new_product_name = preceding_op . name + '__to__' + split_op . name new_product_shape = preceding_op . output . shape new_product = self . _add_product ( new_product_name , new_product_shape ) new_product . producer = preceding_op preceding_op . output = new_product preceding_op . output . consumers . append ( split_op ) split_op . inputs . append ( preceding_op . output )
Insert a Split Op below the preceding Op in the connected graph.
Insert a Split Op below the preceding Op in the connected graph .
"""
        Insert a Split Op below the preceding Op in the connected graph.
        :param preceding_op: Op prior to split op
        :param split_op: Split op to insert
        """ # Important Notes # Op: # An Op class represents a module in a model. # # Product: # In this version of the Winnower, the Product class represents the following entities in a model. # 1) a Tensor between two modules (in Winnower, 2 Ops). # 2) an input # 3) a constant # 4) a parameter # # Considering only the definition #1) above, i.e., Product is a Tensor between 2 Ops, # an Op's inputs and output are Products. # That means, an Op could have multiple input Products and one output Product. # Examples of Op with multiple input products: add, cat (Concat) # A Product's Producer and Consumer are Ops. # A Product could have only one Producer but could have multiple consumers. # For example, a Split Op has one output.  The Split Op's single output isa Product. # That product's single Producer is the Split Op and multiple consumers are the 2 Ops in the 2 branches of # the Split, that receive the Split output. # Steps: # 1. Create a new Product for Split Op's output. # 2.This product has multiple consumers. Add the consumers to the Product. #   Get the consumers from the op's multiple products. # 3. Set the the current Op's output Product's consumer to Split Op. The output product's name must be changed. # 4. Set the Split Op's input to point to current Op's output. Its name must be changed. # 1. Create a new Product for Split Op's output. # 2.This product has multiple consumers. Add the consumers to the Product. # Get the consumers from the op's multiple products. # 3. Create a new product to connect the preceding Op to the Split Op. # Set the the preceding Op's output Product's consumer to Split Op. # The preceding Op's output products (products, since it was behaving like a Split) are going to be deleted, # since a Split is being inserted in the connected graph. # Save the preceding Op's output Product shape. # This is needed to create the new product from the preceding Op to the newly being inserted Split Op. # Since the preceding Op was behaving like a Split Op, it  would have 2 products with the preceding Op as the # producer. Delete these products from the product dictionary. # Important Notes # The following check is needed since ResNet uses the same Relu twice in BasicBlock's forward() # Please read the details comments in _add_consumers_to_split_op_product() # 4. Set the Split Op's input to point to current Op's output. # new_name = preceding_op.name + '__to__' + split_op.name
self
preceding_op
Op
Op prior to split op
Op prior to split op
split_op
Op
Split op to insert
Split op to insert