From: 김용섭/동작제어Lab(SR)/Engineer/삼성전자 Date: Tue, 10 Jul 2018 05:30:56 +0000 (+0900) Subject: Introduce new UnsupportedOperationCount class (#1876) X-Git-Tag: 0.2~479 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c2b1885fa9659d6215a4a9df5eae66fbfe53ef83;p=platform%2Fcore%2Fml%2Fnnfw.git Introduce new UnsupportedOperationCount class (#1876) - This UnsupportedOperationCount class will be used for distinguishing whether an operator can be counted on operation counts. Signed-off-by: Yongseop Kim --- diff --git a/tools/tflitefile_tool/operator_counter.py b/tools/tflitefile_tool/operator_counter.py index 77a4c80..cff0537 100755 --- a/tools/tflitefile_tool/operator_counter.py +++ b/tools/tflitefile_tool/operator_counter.py @@ -40,6 +40,17 @@ class OperationCount(object): def TotalCount(self): return self.add_count + self.mul_count + self.nonlinear_count + def IsSupportedOperationCount(self): + return True + + +class UnsupportedOperationCount(OperationCount): + def __init__(self): + OperationCount.__init__(self) + + def IsSupportedOperationCount(self): + return False + # NOTE: How to count operations of convolution(and also pooling)? # @@ -152,8 +163,8 @@ def CountOpsNothing(tf_operator, inputs, outputs): return OperationCount() -def CountOpsDummy(tf_operator, inputs, outputs): - return OperationCount() +def CountOpsUnsupported(tf_operator, inputs, outputs): + return UnsupportedOperationCount() # TODO: can make this as a class which has above method @@ -167,16 +178,16 @@ ops_counters = { "CONCATENATION": CountOpsNothing, # ADAS - "TOPK_V2": CountOpsDummy, - "SUB": CountOpsDummy, - "STRIDED_SLICE": CountOpsDummy, - "RESHAPE": CountOpsDummy, - "GATHER": CountOpsDummy, - "RESIZE_BILINEAR": CountOpsDummy, - "CAST": CountOpsDummy, - "ADD": CountOpsDummy, - "MUL": CountOpsDummy, - "DIV": CountOpsDummy, - "CUSTOM(TensorFlowMax)": CountOpsDummy, - "CUSTOM": CountOpsDummy, + "TOPK_V2": CountOpsUnsupported, + "SUB": CountOpsUnsupported, + "STRIDED_SLICE": CountOpsUnsupported, + "RESHAPE": CountOpsUnsupported, + "GATHER": CountOpsUnsupported, + "RESIZE_BILINEAR": CountOpsUnsupported, + "CAST": CountOpsUnsupported, + "ADD": CountOpsUnsupported, + "MUL": CountOpsUnsupported, + "DIV": CountOpsUnsupported, + "CUSTOM(TensorFlowMax)": CountOpsUnsupported, + "CUSTOM": CountOpsUnsupported, } diff --git a/tools/tflitefile_tool/operator_parser.py b/tools/tflitefile_tool/operator_parser.py index c6600b0..ac880c6 100755 --- a/tools/tflitefile_tool/operator_parser.py +++ b/tools/tflitefile_tool/operator_parser.py @@ -7,17 +7,21 @@ import tflite.OperatorCode import tflite.BuiltinOperator from operator_wrapping import Operator, SetBuiltinOpcodeStr, BuiltinOpcodeStrList from tensor_wrapping import Tensor, SetTensorTypeStr -from operator_counter import OperationCount +from operator_counter import OperationCount, UnsupportedOperationCount class TypesCounter(object): - def __init__(self): + def __init__(self, op): self.type_count = 0 - self.op_count = OperationCount() + if op.IsSupportedOperationCount(): + self.op_count = OperationCount() + else: + self.op_count = UnsupportedOperationCount() def Update(self, op): self.type_count = self.type_count + 1 - self.op_count.Increase(op.GetOpCount()) + if self.op_count.IsSupportedOperationCount(): + self.op_count.Increase(op.GetOpCount()) def GetTypeCount(self): return self.type_count @@ -25,6 +29,9 @@ class TypesCounter(object): def GetOpCount(self): return self.op_count + def IsSupportedOperationCount(self): + return self.op_count.IsSupportedOperationCount() + class OperatorParser(object): def __init__(self, tf_model, tf_subgraph, perf_predictor=None): @@ -66,7 +73,7 @@ class OperatorParser(object): def CountOperator(self, op): opcode_str = op.GetOpcodeStr() if opcode_str not in self.op_types: - self.op_types[opcode_str] = TypesCounter() + self.op_types[opcode_str] = TypesCounter(op) self.op_types[opcode_str].Update(op) def GetInputTensors(self, tf_operator): @@ -104,15 +111,17 @@ class OperatorParser(object): total_opstr_count = 0 total_op_count = 0 for opstr, type_counter in self.op_types.items(): + supported = type_counter.IsSupportedOperationCount() + opstr_count = type_counter.GetTypeCount() op_count = type_counter.GetOpCount().TotalCount() - print("\t{0:38}: {1:4} \t (total_ops: {2})".format(opstr, opstr_count, - "{:,}".format(op_count))) + print("\t{0:38}: {1:4} \t (total_ops: {2})".format( + opstr, opstr_count, "{:,}".format(op_count) if supported else "???")) total_opstr_count = total_opstr_count + opstr_count - total_op_count = total_op_count + op_count + total_op_count = (total_op_count + op_count) if supported else total_op_count - print("{0:46}: {1:4} \t (total_ops: {2})".format("Total Number of operators", - total_opstr_count, - "{:,}".format(total_op_count))) + total_op_count = "{:,}".format(total_op_count) + print("{0:46}: {1:4} \t (total_ops: {2})".format( + "Total Number of operators", total_opstr_count, total_op_count)) diff --git a/tools/tflitefile_tool/operator_wrapping.py b/tools/tflitefile_tool/operator_wrapping.py index 16559f2..6ffcb2f 100755 --- a/tools/tflitefile_tool/operator_wrapping.py +++ b/tools/tflitefile_tool/operator_wrapping.py @@ -4,7 +4,7 @@ import tflite.Operator import tflite.OperatorCode import tflite.BuiltinOperator from tensor_wrapping import Tensor -from operator_counter import OperationCount, ops_counters +from operator_counter import OperationCount, UnsupportedOperationCount, ops_counters from perf_predictor import PerfPredictor BuiltinOpcodeStrList = {} @@ -45,11 +45,18 @@ class Operator(object): self.op_count = None # OperationCount def PrintInfo(self, perf_predictor=None): - cycles = (perf_predictor.PredictCycles( - self.op_count)) if perf_predictor != None else "???" + supported = self.IsSupportedOperationCount() + + # total op counts + counts = "{:,}".format(self.op_count.TotalCount()) if supported else "???" + + # total op cycles + cycles = "{:,}".format((perf_predictor.PredictCycles( + self.op_count))) if supported and perf_predictor != None else "???" + print("Operator {0}: {1} (ops: {2}, cycls: {3})".format( - self.operator_idx, self.opcode_str, "{:,}".format(self.op_count.TotalCount()), - "{:,}".format(cycles))) + self.operator_idx, self.opcode_str, counts, cycles)) + print("\tInput Tensors" + GetStrTensorIndex(self.inputs)) for tensor in self.inputs: tensor.PrintInfo("\t\t") @@ -59,14 +66,18 @@ class Operator(object): def CountOperations(self): opcode_str = self.opcode_str - if opcode_str not in ops_counters: - print("\n\t Operator {0} is not supported yet\n".format(opcode_str)) - return OperationCount() - self.op_count = ops_counters[opcode_str](self.tf_operator, self.inputs, - self.outputs) + # FIXME: if there would be a class for ops_counters, we can delete this + if not opcode_str in ops_counters: + self.op_count = UnsupportedOperationCount() + else: + self.op_count = ops_counters[opcode_str](self.tf_operator, self.inputs, + self.outputs) def GetOpcodeStr(self): return self.opcode_str def GetOpCount(self): return self.op_count + + def IsSupportedOperationCount(self): + return self.op_count.IsSupportedOperationCount()