示例#1
0
文件: math_ops.py 项目: VoltaAI/TFMin
    def gen_code(cls, tf_op, inputs):

        type = code_gen.get_c_dtype(tf_op.outputs[0].dtype.base_dtype)

        param_a_is_scalar = (inputs[0].shape.ndims == 0
                             or (inputs[0].shape.ndims == 1
                                 and inputs[0].shape.dims[0] == 1))
        param_b_is_scalar = (inputs[1].shape.ndims == 0
                             or (inputs[1].shape.ndims == 1
                                 and inputs[1].shape.dims[1] == 1))

        param_a_is_const = tf_utils.operation_is_constant(inputs[0].op)
        param_b_is_const = tf_utils.operation_is_constant(inputs[1].op)

        # if one of the inputs is a constant scalar then implement form 2
        if param_a_is_const and param_a_is_scalar:
            tensor_identifier = code_gen.c_safe_identifier(inputs[1].name)
            const_value = tf_utils.get_const_scalar(
                tf_utils.get_parent_of_tensor(tf_op.inputs[0]))

            return "%s %s * (%s)%s;" % \
                   (base_op.BaseOpKernel.output_assignment(tf_op, True),
                    tensor_identifier,
                    type,
                    str(const_value))

        if param_b_is_const and param_b_is_scalar:
            tensor_identifier = code_gen.c_safe_identifier(inputs[0].name)
            const_value = tf_utils.get_const_scalar(
                tf_utils.get_parent_of_tensor(tf_op.inputs[1]))

            return "%s %s * (%s)%s;" % \
                   (base_op.BaseOpKernel.output_assignment(tf_op, True),
                    tensor_identifier,
                    type,
                    str(const_value))

        # if both inputs are either tensors or not constants then generate form 1
        input0_identifier = code_gen.c_safe_identifier(inputs[0].name)
        input1_identifier = code_gen.c_safe_identifier(inputs[1].name)

        code = "%s %s * %s;" % \
               (base_op.BaseOpKernel.output_assignment(tf_op, eval),
                input0_identifier,
                input1_identifier)
        return code
示例#2
0
文件: math_ops.py 项目: VoltaAI/TFMin
    def gen_code(cls, tf_op, inputs):

        output_identifier = code_gen.c_safe_identifier(tf_op.outputs[0].name)
        input0_identifier = code_gen.c_safe_identifier(inputs[0].name)
        input1_identifier = code_gen.c_safe_identifier(inputs[1].name)

        # if the second argument is a scalar tensor
        input1_shape = tf_utils.np_tensor_shape(inputs[1])
        if len(input1_shape) == 0 or (len(input1_shape) == 1
                                      and input1_shape[0] == 1):

            input0_shape = tf_utils.np_tensor_shape(inputs[0])
            input0_size = np.prod(input0_shape)
            type = code_gen.get_c_dtype(inputs[0].dtype.base_dtype)

            code = cpp_gen.CodeBlock()
            target = "%s" % base_op.BaseOpKernel.output_assignment(
                tf_op, True, assignment=False)
            code.add_statement(
                cpp_gen.Statement(target.replace(";", "").replace('\n', '')))

            # determine the type of expression to use. Either a division by the value of
            # a rank zero tensor, a division by a constant or a shift by a constant
            # in the case of power of two denominators

            if inputs[1].op.type == 'Const':
                const_value = tf_utils.get_const_scalar(inputs[1].op)

                if math.log2(const_value).is_integer():
                    expression = ">> %d" % int(math.log2(const_value))
                else:
                    expression = "/ (%s)%f" % (type, const_value)

            else:

                expression = "/ %s(0)" % input1_identifier

            for_loop = cpp_gen.LoopStatement(
                "for", "int i=0; i<%d; ++i" % input0_size)
            for_loop.code.add_statement(
                cpp_gen.Statement(
                    "((%s*)%s.data())[i] = ((%s*)%s.data())[i] %s" %
                    (type, output_identifier, type, input0_identifier,
                     expression)))

            code.add_statement(for_loop)
        else:
            code = "%s %s / %s;" % \
                   (base_op.BaseOpKernel.output_assignment(tf_op, True),
                    input0_identifier,
                    input1_identifier)

        return code
示例#3
0
文件: beta_ops.py 项目: VoltaAI/TFMin
    def gen_code(cls, tf_op, inputs):

        narrow_range = tf_op.get_attr("narrow_range")
        num_bits = tf_op.get_attr("num_bits")

        range_min = tf_utils.get_const_scalar(
            tf_utils.get_parent_of_tensor(inputs[1]))
        range_max = tf_utils.get_const_scalar(
            tf_utils.get_parent_of_tensor(inputs[2]))

        print("narrow [%s] num_bits [%d] range [%f - %f]" %
              (narrow_range, num_bits, range_min, range_max))

        # output_shape = tf_utils.np_tensor_shape(tf_op.outputs[0])
        # input_identifier = code_gen.c_safe_identifier(tf_op.inputs[0].name)

        # code = "%s %s.reshape(Eigen::array<int, %d>(%s));" % \
        #       (core_ops.output_assignment(tf_op, eval),
        #        input_identifier,
        #        len(output_shape),
        #        code_gen.ndarray_1d_to_literal(output_shape))

        return "// TODO"
示例#4
0
    def gen_code(cls, tf_op, inputs):

        input0_identifier = code_gen.c_safe_identifier(inputs[0].name)
        input1_identifier = code_gen.c_safe_identifier(inputs[1].name)

        axis = tf_utils.get_const_scalar(
            tf_utils.get_parent_of_tensor(inputs[2]))

        # if there is an undefined batch dimension that has been collapsed
        # reduce the axis index by 1
        reduced_rank = len(tf_utils.np_tensor_shape(tf_op.outputs[0]))
        if reduced_rank != tf_op.outputs[0].shape.ndims:
            axis -= (tf_op.outputs[0].shape.ndims - reduced_rank)

        code = "%s %s.concatenate(%s, %d);" % \
               (base_op.BaseOpKernel.output_assignment(tf_op),
                input0_identifier,
                input1_identifier,
                axis)

        return code
示例#5
0
    def gen_code(cls, tf_op, inputs):

        # output_shape = tf_utils.np_tensor_shape(tf_op.outputs[0])
        output_identifier = code_gen.c_safe_identifier(tf_op.outputs[0].name)

        # print("Fill operation looks like this. . .")
        # super().print_operation_details(tf_op)

        type = code_gen.get_c_dtype(tf_op.outputs[0].dtype.base_dtype)
        constant_value = tf_utils.get_const_scalar(
            tf_utils.get_parent_of_tensor(inputs[1]))

        code = cpp_gen.CodeBlock()
        code.add_statement(
            cpp_gen.Statement(
                base_op.BaseOpKernel.output_assignment(tf_op,
                                                       eval=True,
                                                       assignment=False)))

        code.add_statement(
            cpp_gen.Statement("%s.setConstant((%s)%f)" %
                              (output_identifier, type, constant_value)))
        return code
示例#6
0
    def gen_code(cls, tf_op, inputs):

        # base_op.BaseOpKernel.print_operation_details(tf_op)

        num_split = tf_op.get_attr("num_split")

        # This development version only supports the form where axis is
        # provided by a rank 0 constant operation
        if tf_utils.get_parent_of_tensor(inputs[0]).type != "Const":
            print("Error : Split operation doesn't support computed values "
                  "for axis yet!")
            return "// Error : Couldn't produce split operation with a " \
                   "computed axis dimension."

        # axis is provided by the first input tensor
        axis = tf_utils.get_const_scalar(
            tf_utils.get_parent_of_tensor(inputs[0]))

        # if there is an undefined batch dimension that has been collapsed
        # reduce the axis index by 1
        reduced_rank = len(tf_utils.np_tensor_shape(tf_op.outputs[0]))
        if reduced_rank != tf_op.outputs[0].shape.ndims:
            axis -= (tf_op.outputs[0].shape.ndims - reduced_rank)

        code = ""

        # if num_split is an integer then generate form 1 of this
        # operation where the input tensor is split into
        # num_split tensors, divided evenly along axis
        if type(num_split) is int:

            # verify that the size of dimenions 'axis' is a muliple of num_split
            input_axis_size = tf_utils.np_tensor_shape(inputs[1])[axis]
            if input_axis_size % num_split != 0:
                print("Error : Split operation trying to split dimenson of "
                      "size %d into %d parts, leaves remainder." %
                      (input_axis_size, num_split))
                return "// Error : Couldn't produce split operation where " \
                       "tensor doesn't divide into num_split parts"

            # Calculate the size in 'axis' of each output slice
            size = input_axis_size / num_split

            input1_identifier = code_gen.c_safe_identifier(inputs[1].name)
            rank = len(tf_utils.np_tensor_shape(inputs[1]))

            offset = np.zeros(rank, dtype=int)
            extents = tf_utils.np_tensor_shape(inputs[1])
            extents[axis] = size

            # generate code for each output tensor
            for idx in range(num_split):
                code += base_op.BaseOpKernel.output_assignment(tf_op, idx=idx)

                offset[axis] = idx * size

                code += " %s.slice(Eigen::array<int, %d>(%s), " \
                        "Eigen::array<int, %d>(%s));" % \
                        (input1_identifier,
                         rank,
                         code_gen.ndarray_1d_to_literal(offset),
                         rank,
                         code_gen.ndarray_1d_to_literal(extents)
                         )

        else:  # TODO need to implement this
            code = "// Error Split operation does not currently " \
                   "support arbitrary sized splits"

        return code