nncf/common/pruning/node_selector.py
def create_pruning_groups(self, graph: NNCFGraph) -> Clusterization[NNCFNode]:
        """
        This function groups ALL nodes with pruning types to groups that should be pruned together.
            1. Create clusters for special ops (eltwises) that should be pruned together
            2. Create groups of nodes that should be pruned together (taking into account clusters of special ops)
            3. Add remaining single nodes
            4. Unite clusters for Conv + Depthwise conv (should be pruned together too)
            5. Checks for groups (all nodes in group can prune or all group can't be pruned)
        Return groups of modules that should be pruned together.

        :param graph: Graph to work with and their initialization parameters as values.
        :return: Clusterization of pruned nodes.
        """
        # pylint:disable=too-many-branches
        all_nodes_to_prune = graph.get_nodes_by_types(self._prune_operations_types)  # NNCFNodes here

        # 1. Clusters for special ops
        identity_like_types = self._identity_mask_propagation_op_metatype.get_all_op_aliases()
        special_ops_clusterization = cluster_special_ops(graph, self._grouping_operations_types,
                                                         identity_like_types)

        pruned_nodes_clusterization = Clusterization[NNCFNode](lambda x: x.node_id)

        # 2. Clusters for nodes that should be pruned together (taking into account clusters for special ops)
        for i, cluster in enumerate(special_ops_clusterization.get_all_clusters()):
            all_pruned_inputs = {}
            clusters_to_merge = []

            for node in cluster.elements:
                sources = get_sources_of_node(node, graph, self._prune_operations_types)
                for source_node in sources:
                    if pruned_nodes_clusterization.is_node_in_clusterization(source_node.node_id):
                        # Merge clusters if some node already added in another cluster
                        cluster = pruned_nodes_clusterization.get_cluster_containing_element(source_node.node_id)
                        clusters_to_merge.append(cluster.id)
                    elif source_node.node_id not in all_pruned_inputs:
                        all_pruned_inputs[source_node.node_id] = source_node

            if all_pruned_inputs:
                cluster = Cluster[NNCFNode](i, all_pruned_inputs.values(), all_pruned_inputs.keys())
                clusters_to_merge.append(cluster.id)
                pruned_nodes_clusterization.add_cluster(cluster)

            # Merge clusters if one source node in several special ops clusters
            pruned_nodes_clusterization.merge_list_of_clusters(clusters_to_merge)

        last_cluster_idx = len(special_ops_clusterization.get_all_clusters())

        # 3. Add remaining single nodes as separate clusters
        for node in all_nodes_to_prune:
            if not pruned_nodes_clusterization.is_node_in_clusterization(node.node_id):
                cluster = Cluster[NNCFNode](last_cluster_idx, [node], [node.node_id])
                pruned_nodes_clusterization.add_cluster(cluster)

                last_cluster_idx += 1

        stop_propagation_ops = self._stop_propagation_op_metatype.get_all_op_aliases()
        # 4. Merge clusters for Conv + Depthwise conv (should be pruned together too)
        for node in all_nodes_to_prune:
            cluster_id = pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id

            if is_prunable_depthwise_conv(node):
                previous_convs = get_previous_convs(graph, node, self._prune_operations_types, stop_propagation_ops)
                previous_clusters = [
                    pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                    for node in previous_convs
                ]
                pruned_nodes_clusterization.merge_list_of_clusters([cluster_id] + previous_clusters)

        # 5. Merge nodes into one cluster if some module forwards several times
        multiforward_nodes = self._get_multiforward_nodes(graph)
        for list_of_nodes in multiforward_nodes:
            clusters_to_merge = [pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                                 for node in list_of_nodes]
            pruned_nodes_clusterization.merge_list_of_clusters(clusters_to_merge)

            # Merge previous convolutions into one cluster
            all_previous_convs = []
            for node in list_of_nodes:
                nncf_node = graph.get_node_by_id(node.node_id)
                previous_convs = get_previous_convs(graph, nncf_node, self._prune_operations_types,
                                                    stop_propagation_ops)
                # Check if previous node isn't multiforward,
                # in case of multiforward nodes cycle
                for previous_conv in previous_convs:
                    if previous_conv not in list_of_nodes:
                        all_previous_convs.append(previous_conv)

            previous_clusters = [
                pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                for node in all_previous_convs
            ]
            pruned_nodes_clusterization.merge_list_of_clusters(previous_clusters)

        # 6. Checks for groups (all nodes in group can be pruned or all group can't be pruned).
        model_analyser = ModelAnalyzer(graph, self._pruning_operator_metatypes, is_prunable_depthwise_conv)
        can_prune_analysis = model_analyser.analyse_model_before_pruning()
        can_prune_and_should_prune_analysis = self._should_prune_groups_analysis(graph,
                                                                                 pruned_nodes_clusterization,
                                                                                 can_prune_analysis)
        can_prune_final_analysis = self._pruning_dimensions_analysis(graph, can_prune_and_should_prune_analysis)
        self._filter_groups(pruned_nodes_clusterization, can_prune_final_analysis)
        return pruned_nodes_clusterization

        This function groups ALL nodes with pruning types to groups that should be pruned together.
            1. Create clusters for special ops (eltwises) that should be pruned together
            2. Create groups of nodes that should be pruned together (taking into account clusters of special ops)
            3. Add remaining single nodes
            4. Unite clusters for Conv + Depthwise conv (should be pruned together too)
            5. Checks for groups (all nodes in group can prune or all group can't be pruned)
        Return groups of modules that should be pruned together.

        :param graph: Graph to work with and their initialization parameters as values.
        :return: Clusterization of pruned nodes.
        
This function groups ALL nodes with pruning types to groups that should be pruned together.
1. Create clusters for special ops (eltwises) that should be pruned together
2. Create groups of nodes that should be pruned together (taking into account clusters of special ops)
3. Add remaining single nodes
4. Unite clusters for Conv + Depthwise conv (should be pruned together too)
5. Checks for groups (all nodes in group can prune or all group can't be pruned)
Return groups of modules that should be pruned together.
This function groups ALL nodes with pruning types to groups that should be pruned together . 1 . Create clusters for special ops ( eltwises ) that should be pruned together 2 . Create groups of nodes that should be pruned together ( taking into account clusters of special ops ) 3 . Add remaining single nodes 4 . Unite clusters for Conv + Depthwise conv ( should be pruned together too ) 5 . Checks for groups ( all nodes in group can prune or all group can ' t be pruned ) Return groups of modules that should be pruned together .
def create_pruning_groups(self, graph: NNCFGraph) -> Clusterization[NNCFNode]:
        all_nodes_to_prune = graph.get_nodes_by_types(self._prune_operations_types)  
        identity_like_types = self._identity_mask_propagation_op_metatype.get_all_op_aliases()
        special_ops_clusterization = cluster_special_ops(graph, self._grouping_operations_types,
                                                         identity_like_types)
        pruned_nodes_clusterization = Clusterization[NNCFNode](lambda x: x.node_id)
        for i, cluster in enumerate(special_ops_clusterization.get_all_clusters()):
            all_pruned_inputs = {}
            clusters_to_merge = []
            for node in cluster.elements:
                sources = get_sources_of_node(node, graph, self._prune_operations_types)
                for source_node in sources:
                    if pruned_nodes_clusterization.is_node_in_clusterization(source_node.node_id):
                        cluster = pruned_nodes_clusterization.get_cluster_containing_element(source_node.node_id)
                        clusters_to_merge.append(cluster.id)
                    elif source_node.node_id not in all_pruned_inputs:
                        all_pruned_inputs[source_node.node_id] = source_node
            if all_pruned_inputs:
                cluster = Cluster[NNCFNode](i, all_pruned_inputs.values(), all_pruned_inputs.keys())
                clusters_to_merge.append(cluster.id)
                pruned_nodes_clusterization.add_cluster(cluster)
            pruned_nodes_clusterization.merge_list_of_clusters(clusters_to_merge)
        last_cluster_idx = len(special_ops_clusterization.get_all_clusters())
        for node in all_nodes_to_prune:
            if not pruned_nodes_clusterization.is_node_in_clusterization(node.node_id):
                cluster = Cluster[NNCFNode](last_cluster_idx, [node], [node.node_id])
                pruned_nodes_clusterization.add_cluster(cluster)
                last_cluster_idx += 1
        stop_propagation_ops = self._stop_propagation_op_metatype.get_all_op_aliases()
        for node in all_nodes_to_prune:
            cluster_id = pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
            if is_prunable_depthwise_conv(node):
                previous_convs = get_previous_convs(graph, node, self._prune_operations_types, stop_propagation_ops)
                previous_clusters = [
                    pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                    for node in previous_convs
                ]
                pruned_nodes_clusterization.merge_list_of_clusters([cluster_id] + previous_clusters)
        multiforward_nodes = self._get_multiforward_nodes(graph)
        for list_of_nodes in multiforward_nodes:
            clusters_to_merge = [pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                                 for node in list_of_nodes]
            pruned_nodes_clusterization.merge_list_of_clusters(clusters_to_merge)
            all_previous_convs = []
            for node in list_of_nodes:
                nncf_node = graph.get_node_by_id(node.node_id)
                previous_convs = get_previous_convs(graph, nncf_node, self._prune_operations_types,
                                                    stop_propagation_ops)
                for previous_conv in previous_convs:
                    if previous_conv not in list_of_nodes:
                        all_previous_convs.append(previous_conv)
            previous_clusters = [
                pruned_nodes_clusterization.get_cluster_containing_element(node.node_id).id
                for node in all_previous_convs
            ]
            pruned_nodes_clusterization.merge_list_of_clusters(previous_clusters)
        model_analyser = ModelAnalyzer(graph, self._pruning_operator_metatypes, is_prunable_depthwise_conv)
        can_prune_analysis = model_analyser.analyse_model_before_pruning()
        can_prune_and_should_prune_analysis = self._should_prune_groups_analysis(graph,
                                                                                 pruned_nodes_clusterization,
                                                                                 can_prune_analysis)
        can_prune_final_analysis = self._pruning_dimensions_analysis(graph, can_prune_and_should_prune_analysis)
        self._filter_groups(pruned_nodes_clusterization, can_prune_final_analysis)
        return pruned_nodes_clusterization
def create_pruning_groups ( self , graph : NNCFGraph ) -> Clusterization [ NNCFNode ] : all_nodes_to_prune = graph . get_nodes_by_types ( self . _prune_operations_types ) identity_like_types = self . _identity_mask_propagation_op_metatype . get_all_op_aliases ( ) special_ops_clusterization = cluster_special_ops ( graph , self . _grouping_operations_types , identity_like_types ) pruned_nodes_clusterization = Clusterization [ NNCFNode ] ( lambda x : x . node_id ) for i , cluster in enumerate ( special_ops_clusterization . get_all_clusters ( ) ) : all_pruned_inputs = { } clusters_to_merge = [ ] for node in cluster . elements : sources = get_sources_of_node ( node , graph , self . _prune_operations_types ) for source_node in sources : if pruned_nodes_clusterization . is_node_in_clusterization ( source_node . node_id ) : cluster = pruned_nodes_clusterization . get_cluster_containing_element ( source_node . node_id ) clusters_to_merge . append ( cluster . id ) elif source_node . node_id not in all_pruned_inputs : all_pruned_inputs [ source_node . node_id ] = source_node if all_pruned_inputs : cluster = Cluster [ NNCFNode ] ( i , all_pruned_inputs . values ( ) , all_pruned_inputs . keys ( ) ) clusters_to_merge . append ( cluster . id ) pruned_nodes_clusterization . add_cluster ( cluster ) pruned_nodes_clusterization . merge_list_of_clusters ( clusters_to_merge ) last_cluster_idx = len ( special_ops_clusterization . get_all_clusters ( ) ) for node in all_nodes_to_prune : if not pruned_nodes_clusterization . is_node_in_clusterization ( node . node_id ) : cluster = Cluster [ NNCFNode ] ( last_cluster_idx , [ node ] , [ node . node_id ] ) pruned_nodes_clusterization . add_cluster ( cluster ) last_cluster_idx += 1 stop_propagation_ops = self . _stop_propagation_op_metatype . get_all_op_aliases ( ) for node in all_nodes_to_prune : cluster_id = pruned_nodes_clusterization . get_cluster_containing_element ( node . node_id ) . id if is_prunable_depthwise_conv ( node ) : previous_convs = get_previous_convs ( graph , node , self . _prune_operations_types , stop_propagation_ops ) previous_clusters = [ pruned_nodes_clusterization . get_cluster_containing_element ( node . node_id ) . id for node in previous_convs ] pruned_nodes_clusterization . merge_list_of_clusters ( [ cluster_id ] + previous_clusters ) multiforward_nodes = self . _get_multiforward_nodes ( graph ) for list_of_nodes in multiforward_nodes : clusters_to_merge = [ pruned_nodes_clusterization . get_cluster_containing_element ( node . node_id ) . id for node in list_of_nodes ] pruned_nodes_clusterization . merge_list_of_clusters ( clusters_to_merge ) all_previous_convs = [ ] for node in list_of_nodes : nncf_node = graph . get_node_by_id ( node . node_id ) previous_convs = get_previous_convs ( graph , nncf_node , self . _prune_operations_types , stop_propagation_ops ) for previous_conv in previous_convs : if previous_conv not in list_of_nodes : all_previous_convs . append ( previous_conv ) previous_clusters = [ pruned_nodes_clusterization . get_cluster_containing_element ( node . node_id ) . id for node in all_previous_convs ] pruned_nodes_clusterization . merge_list_of_clusters ( previous_clusters ) model_analyser = ModelAnalyzer ( graph , self . _pruning_operator_metatypes , is_prunable_depthwise_conv ) can_prune_analysis = model_analyser . analyse_model_before_pruning ( ) can_prune_and_should_prune_analysis = self . _should_prune_groups_analysis ( graph , pruned_nodes_clusterization , can_prune_analysis ) can_prune_final_analysis = self . _pruning_dimensions_analysis ( graph , can_prune_and_should_prune_analysis ) self . _filter_groups ( pruned_nodes_clusterization , can_prune_final_analysis ) return pruned_nodes_clusterization
This function groups ALL nodes with pruning types to groups that should be pruned together.
This function groups ALL nodes with pruning types to groups that should be pruned together .
"""
        This function groups ALL nodes with pruning types to groups that should be pruned together.
            1. Create clusters for special ops (eltwises) that should be pruned together
            2. Create groups of nodes that should be pruned together (taking into account clusters of special ops)
            3. Add remaining single nodes
            4. Unite clusters for Conv + Depthwise conv (should be pruned together too)
            5. Checks for groups (all nodes in group can prune or all group can't be pruned)
        Return groups of modules that should be pruned together.

        :param graph: Graph to work with and their initialization parameters as values.
        :return: Clusterization of pruned nodes.
        """ # pylint:disable=too-many-branches # NNCFNodes here # 1. Clusters for special ops # 2. Clusters for nodes that should be pruned together (taking into account clusters for special ops) # Merge clusters if some node already added in another cluster # Merge clusters if one source node in several special ops clusters # 3. Add remaining single nodes as separate clusters # 4. Merge clusters for Conv + Depthwise conv (should be pruned together too) # 5. Merge nodes into one cluster if some module forwards several times # Merge previous convolutions into one cluster # Check if previous node isn't multiforward, # in case of multiforward nodes cycle # 6. Checks for groups (all nodes in group can be pruned or all group can't be pruned).
Clusterization of pruned nodes.
Clusterization of pruned nodes .
self
graph
NNCFGraph
Graph to work with and their initialization parameters as values.
Graph to work with and their initialization parameters as values .