Example #1
0
    def validate(loaded_json):
        try:
            jsonschema.validate(loaded_json, schema=ROOT_NNCF_CONFIG_SCHEMA)
        except jsonschema.ValidationError as e:
            logger.error("Invalid NNCF config supplied!")

            # The default exception's __str__ result will contain the entire schema,
            # which is too large to be readable.
            msg = e.message + ". See documentation or {} for an NNCF configuration file JSON schema definition".format(
                nncf.config_schema.__file__)
            raise jsonschema.ValidationError(msg)

        compression_section = loaded_json.get("compression")
        if compression_section is None:
            # No compression specified
            return

        try:
            if isinstance(compression_section, dict):
                validate_single_compression_algo_schema(compression_section)
            else:
                # Passed a list of dicts
                for compression_algo_dict in compression_section:
                    validate_single_compression_algo_schema(compression_algo_dict)
        except jsonschema.ValidationError:
            # No need to trim the exception output here since only the compression algo
            # specific sub-schema will be shown, which is much shorter than the global schema
            logger.error("Invalid NNCF config supplied!")
            raise
Example #2
0
    def _paint_activation_quantizer_node(
            nncf_graph: NNCFGraph, quantizer_id: NonWeightQuantizerId,
            quantizer_info: 'NonWeightQuantizerInfo',
            bits_color_map: Dict[int, str],
            groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers):
        #pylint:disable=too-many-branches
        affected_insertion_infos_list = quantizer_info.affected_insertions  # type: List[InsertionInfo]

        for insertion_info in affected_insertion_infos_list:
            input_agnostic_op_exec_context = insertion_info.op_exec_context.input_agnostic
            affected_nncf_node_key = nncf_graph.get_node_key_by_iap_context(
                input_agnostic_op_exec_context)
            affected_nx_node = nncf_graph.get_nx_node_by_key(
                affected_nncf_node_key)
            operator_name = affected_nx_node[
                NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name
            node_id = affected_nx_node[NNCFGraph.ID_NODE_ATTR]

            affected_nncf_node = nncf_graph.get_node_by_id(node_id)
            affected_nx_node['label'] = '_#'.join(
                [operator_name, str(node_id)])

            if insertion_info.is_input:
                # Module UpdateInputs pre-op used for activation quantization
                previous_nodes = nncf_graph.get_previous_nodes(
                    affected_nncf_node)

                # Relying on the _quantize_inputs behaviour of only being able to quantize 0-th input

                # previous_nodes are either UpdateWeights, or UpdateWeights + UpdateInputs
                assert len(previous_nodes) == 2 or len(previous_nodes) == 1

                if len(previous_nodes) == 2:
                    if "UpdateInputs" in str(
                            previous_nodes[0].op_exec_context.input_agnostic):
                        target_node = previous_nodes[0]
                    else:
                        target_node = previous_nodes[1]
                else:
                    target_node = previous_nodes[0]
                target_nncf_node_id = target_node.node_id
                target_nncf_node_key = nncf_graph.get_node_key_by_id(
                    target_nncf_node_id)
            else:
                in_port_id = insertion_info.in_port_id

                if in_port_id is None:
                    # Post-hooking used for activation quantization
                    # Currently only a single post-hook can immediately follow an operation
                    succs = list(
                        nncf_graph.get_successors(affected_nncf_node_key))
                    assert len(succs) == 1
                    target_nncf_node_key = succs[0]
                else:
                    # Pre-hooking used for activation quantization
                    previous_nodes = nncf_graph.get_previous_nodes(
                        affected_nncf_node)
                    target_node = None
                    for prev_node in previous_nodes:
                        prev_edge = nncf_graph.get_nx_edge(
                            prev_node, affected_nncf_node)
                        if prev_edge[NNCFGraph.
                                     IN_PORT_NAME_EDGE_ATTR] == in_port_id:
                            target_node = prev_node
                            break

                    assert target_node is not None, "Could not find a pre-hook quantizer node for a specific " \
                                                    "input port!"
                    target_nncf_node_id = target_node.node_id
                    target_nncf_node_key = nncf_graph.get_node_key_by_id(
                        target_nncf_node_id)

            activation_fq_node = nncf_graph.get_nx_node_by_key(
                target_nncf_node_key)
            bits = quantizer_info.quantizer_module_ref.num_bits
            activation_fq_node['color'] = bits_color_map[bits]
            activation_fq_node['style'] = 'filled'
            node_id = activation_fq_node[NNCFGraph.ID_NODE_ATTR]

            activation_fq_node['label'] = 'AFQ_[{}]_#{}'.format(
                quantizer_info.quantizer_module_ref.get_current_config(),
                str(node_id))
            grouped_mode = bool(groups_of_adjacent_quantizers)
            if grouped_mode:
                group_id_str = 'UNDEFINED'
                group_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(
                    quantizer_id)
                if node_id is None:
                    nncf_logger.error(
                        'No group for activation quantizer: {}'.format(
                            target_nncf_node_key))
                else:
                    group_id_str = str(group_id)
                activation_fq_node['label'] += "_G" + group_id_str
Example #3
0
    def get_bitwidth_graph(algo_ctrl, model, all_quantizers_per_full_scope,
                           groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers) -> NNCFGraph:
        grouped_mode = bool(groups_of_adjacent_quantizers)
        nncf_graph = model.get_graph()
        for node_key in nncf_graph.get_all_node_keys():
            node = nncf_graph.get_nx_node_by_key(node_key)
            color = ''
            if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]:
                operator_name = node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name
                scope = node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].input_agnostic.scope_in_model
                module = model.get_module_by_scope(scope)
                if isinstance(module, NNCFConv2d):
                    color = 'lightblue'
                    if module.groups == module.in_channels:
                        operator_name = 'DW_Conv2d'
                        color = 'purple'
                if not grouped_mode:
                    operator_name += '_#{}'.format(str(node[NNCFGraph.ID_NODE_ATTR]))
                node['label'] = operator_name
                node['style'] = 'filled'
                if color:
                    node['color'] = color

        non_weight_quantizers = algo_ctrl.non_weight_quantizers
        bits_color_map = {4: 'red', 8: 'green', 6: 'orange'}
        for quantizer_id, quantizer_info in non_weight_quantizers.items():
            affected_iap_ctx_list = quantizer_info.affected_ia_op_exec_contexts
            for activation_iap_ctx in affected_iap_ctx_list:
                post_hooked_nx_node_key = nncf_graph.get_node_id_by_iap_context(activation_iap_ctx)
                post_hooked_module_node = nncf_graph.get_nx_node_by_key(post_hooked_nx_node_key)
                operator_name = post_hooked_module_node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name
                if not grouped_mode:
                    operator_name += '_#{}'.format(str(post_hooked_module_node[NNCFGraph.ID_NODE_ATTR]))
                post_hooked_module_node['label'] = operator_name

                for next_nx_node_key in nncf_graph.get_successors(post_hooked_nx_node_key):
                    activation_fq_node = nncf_graph.get_nx_node_by_key(next_nx_node_key)
                    activation_quantizer = non_weight_quantizers[quantizer_id].quantizer_module_ref
                    bits = activation_quantizer.num_bits

                    activation_fq_node['color'] = bits_color_map[bits]
                    activation_fq_node['style'] = 'filled'
                    node_id = activation_fq_node[NNCFGraph.ID_NODE_ATTR]
                    if grouped_mode:
                        node_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(activation_quantizer)
                        if node_id is None:
                            nncf_logger.error('No group for activation quantizer: {}'.format(next_nx_node_key))
                            node_id = 'UNDEFINED'
                    activation_fq_node['label'] = '{}_bit__AFQ_#{}'.format(bits, str(node_id))

        for scope, quantizer in all_quantizers_per_full_scope.items():
            if quantizer.is_weights:
                node = nncf_graph.find_node_in_nx_graph_by_scope(scope)
                if node is None:
                    raise AttributeError('Failed to get node by scope={}'.format(str(scope)))
                if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]:
                    bits = quantizer.num_bits
                    node_id = node[NNCFGraph.ID_NODE_ATTR]
                    if grouped_mode:
                        node_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(quantizer)
                        if node_id is None:
                            nncf_logger.error('No group for weight quantizer: {}'.format(scope))
                            node_id = 'UNDEFINED'
                    node['label'] = '{}_bit__WFQ_#{}'.format(bits, str(node_id))
                    node['color'] = bits_color_map[bits]
                    node['style'] = 'filled'
        return nncf_graph
Example #4
0
    def get_bitwidth_graph(
        algo_ctrl, model, all_quantizers_per_full_scope,
        groups_of_adjacent_quantizers: GroupsOfAdjacentQuantizers
    ) -> NNCFGraph:
        # Overwrites nodes that were obtained during graph tracing and correspond to quantizer
        # nodes with the nodes whose 'label' attribute is set to a more display-friendly representation
        # of the quantizer's bitwidth.
        #pylint:disable=too-many-branches
        grouped_mode = bool(groups_of_adjacent_quantizers)
        nncf_graph = model.get_graph()
        for node_key in nncf_graph.get_all_node_keys():
            node = nncf_graph.get_nx_node_by_key(node_key)
            color = ''
            if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]:
                operator_name = node[
                    NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR].operator_name
                scope = node[
                    NNCFGraph.
                    OP_EXEC_CONTEXT_NODE_ATTR].input_agnostic.scope_in_model
                module = model.get_module_by_scope(scope)
                if isinstance(module, NNCFConv2d):
                    color = 'lightblue'
                    if module.groups == module.in_channels:
                        operator_name = 'DW_Conv2d'
                        color = 'purple'
                operator_name += '_#{}'.format(
                    str(node[NNCFGraph.ID_NODE_ATTR]))
                node['label'] = operator_name
                node['style'] = 'filled'
                if color:
                    node['color'] = color

        non_weight_quantizers = algo_ctrl.non_weight_quantizers
        bits_color_map = {2: 'purple', 4: 'red', 8: 'green', 6: 'orange'}
        for quantizer_id, quantizer_info in non_weight_quantizers.items():
            HAWQDebugger._paint_activation_quantizer_node(
                nncf_graph, quantizer_id, quantizer_info, bits_color_map,
                groups_of_adjacent_quantizers)

        for scope, quantizer in all_quantizers_per_full_scope.items():
            if not quantizer.is_weights:
                continue
            node = nncf_graph.find_node_in_nx_graph_by_scope(scope)
            if node is None:
                raise AttributeError('Failed to get node by scope={}'.format(
                    str(scope)))
            if node[NNCFGraph.OP_EXEC_CONTEXT_NODE_ATTR]:
                bits = quantizer.num_bits
                node_id = node[NNCFGraph.ID_NODE_ATTR]
                node['label'] = 'WFQ_[{}]_#{}'.format(
                    quantizer.get_current_config(), str(node_id))
                if grouped_mode:
                    group_id_str = 'UNDEFINED'
                    normalized_scope = deepcopy(scope)
                    normalized_scope.pop()  # SymmetricQuantizer
                    normalized_scope.pop()  # UpdateWeights
                    normalized_scope.pop()  # ModuleDict[pre_ops]
                    for wq_id in algo_ctrl.weight_quantizers.keys():
                        if wq_id.get_scope() == normalized_scope:
                            quantizer_id = wq_id
                            break
                    else:
                        raise RuntimeError(
                            "Could not associate a weight quantizer inside a model with any "
                            "weight quantizer registered in the quantization controller!"
                        )
                    group_id = groups_of_adjacent_quantizers.get_group_id_for_quantizer(
                        quantizer_id)
                    if group_id is None:
                        nncf_logger.error(
                            'No group for weight quantizer: {}'.format(scope))
                    else:
                        group_id_str = str(group_id)
                    node['label'] += '_G' + group_id_str
                node['color'] = bits_color_map[bits]
                node['style'] = 'filled'
        return nncf_graph