Clone current graph. Use parameter copy_value to control whether to do a Shallow Copy or Deep Copy. For copy_value = True, there will be a copy of each parameter in your network. ATTENTION: it might cause gpu memory overflow. For copy_value = False, clon
(self, copy_value: bool = False)
| 838 | return state |
| 839 | |
| 840 | def copy(self, copy_value: bool = False): |
| 841 | """Clone current graph. |
| 842 | Use parameter copy_value to control whether to do a Shallow Copy or Deep Copy. |
| 843 | |
| 844 | For copy_value = True, there will be a copy of each parameter in your network. |
| 845 | ATTENTION: it might cause gpu memory overflow. |
| 846 | For copy_value = False, cloned network will share the same parameter tensor of current one. |
| 847 | |
| 848 | ATTENTION: all quantization config will be cloned, |
| 849 | all scales and offsets will be cloned even with copy_valye = False. |
| 850 | |
| 851 | Shallow Copy: Shallow repetition is quicker. |
| 852 | However, it's “lazy” it handles pointers and references. |
| 853 | Rather than creating a contemporary copy of the particular knowledge the pointer points to, |
| 854 | it simply copies over the pointer price. |
| 855 | So, each the first and therefore the copy can have pointers that reference constant underlying knowledge. |
| 856 | |
| 857 | Deep Copy: Deep repetition truly clones the underlying data. |
| 858 | It is not shared between the first and therefore the copy. |
| 859 | """ |
| 860 | from ppq.IR.quantize import QuantableOperation |
| 861 | cloned = BaseGraph(name=self._name, built_from=self._built_from) |
| 862 | for op in self.operations.values(): cloned.append_operation(op.copy()) |
| 863 | for var in self.variables.values(): cloned.append_variable(var.copy(copy_value=copy_value)) |
| 864 | |
| 865 | # notice that all operations is copyed without link, so do all variables |
| 866 | # relink them with following code |
| 867 | config_dict = {} |
| 868 | for op in self.operations.values(): |
| 869 | assert op.name in cloned.operations, ( |
| 870 | f'Graph Copy Error, Operation {op.name} is not correctly cloned') |
| 871 | c_op = cloned.operations[op.name] |
| 872 | for i_var in op.inputs: |
| 873 | assert i_var.name in cloned.variables, ( |
| 874 | f'Graph Copy Error, Variable {i_var.name} is not correctly cloned') |
| 875 | ci_var = cloned.variables[i_var.name] |
| 876 | cloned.create_link_with_op( |
| 877 | variable=ci_var, A=ci_var.source_op, B=c_op) |
| 878 | for o_var in op.outputs: |
| 879 | assert o_var.name in cloned.variables, ( |
| 880 | f'Graph Copy Error, Variable {o_var.name} is not correctly cloned') |
| 881 | co_var = cloned.variables[o_var.name] |
| 882 | c_op.outputs.append(co_var) |
| 883 | co_var.source_op = c_op |
| 884 | if isinstance(op, QuantableOperation): |
| 885 | for cfg, var in op.config_with_variable: |
| 886 | config_dict[cfg._hash] = (op, var) |
| 887 | |
| 888 | # relink config to there cloned master. |
| 889 | for c_op in cloned.operations.values(): |
| 890 | if isinstance(c_op, QuantableOperation): |
| 891 | for cfg, var in c_op.config_with_variable: |
| 892 | if cfg.dominated_by != cfg: |
| 893 | assert cfg.dominated_by._hash in config_dict, ( |
| 894 | 'Graph Copy Error, can not find a corresponding master config.') |
| 895 | op, var = config_dict[cfg.dominated_by._hash] |
| 896 | |
| 897 | op = cloned.operations[op.name] |
nothing calls this directly
no test coverage detected