Exemple #1
0
        /// <summary>
        /// Creates a TF_Operation.
        /// </summary>
        /// <param name="graph">a `Graph`.</param>
        /// <param name="node_def">`node_def_pb2.NodeDef` for the operation to create.</param>
        /// <param name="inputs">
        /// A list of `Tensor`s (corresponding to scalar inputs) and lists of
        /// `Tensor`s (corresponding to sequence inputs, e.g. "int64 * N",
        /// "list(int64)"). The length of the list should be equal to the number of
        /// inputs specified by this operation's op def.
        /// </param>
        /// <param name="control_inputs">A list of `Operation`s to set as control dependencies.</param>
        /// <returns>A wrapped TF_Operation*.</returns>
        public static (IntPtr, OperationDescription) _create_c_op(Graph graph, NodeDef node_def, Tensor[] inputs, Operation[] control_inputs,
                                                                  OpDef op_def = null)
        {
            if (op_def == null)
            {
                op_def = graph.GetOpDef(node_def.Op);
            }

            var input_tensors = _reconstruct_sequence_inputs(op_def, inputs, node_def.Attr);

            lock (Locks.ProcessWide)
            {
                var op_desc = graph.NewOperation(node_def.Op, node_def.Name);

                if (!string.IsNullOrEmpty(node_def.Device))
                {
                    c_api.TF_SetDevice(op_desc, node_def.Device);
                }

                // Add inputs
                foreach (var op_input in input_tensors)
                {
                    if (op_input.IsList)
                    {
                        c_api.TF_AddInputList(op_desc, op_input.Select(x => x._as_tf_output()).ToArray(), op_input.Count());
                    }
                    else if (op_input.Count() == 1)
                    {
                        c_api.TF_AddInput(op_desc, op_input[0]._as_tf_output());
                    }
                }

                var status = tf.Status;

                // Add control inputs
                foreach (var control_input in control_inputs)
                {
                    c_api.TF_AddControlInput(op_desc, control_input);
                }

                // Add attrs
                foreach (var attr in node_def.Attr)
                {
                    var bytes       = attr.Value.ToByteArray(); //TODO: we can use attr.Value.WriteTo with a memory stream.
                    var protoHandle = Marshal.AllocHGlobal(bytes.Length);
                    Marshal.Copy(bytes, 0, protoHandle, bytes.Length);
                    uint len = (uint)bytes.Length;
                    c_api.TF_SetAttrValueProto(op_desc, attr.Key, protoHandle, proto_len: len, status: status.Handle);
                    status.Check(true);
                    Marshal.FreeHGlobal(protoHandle);
                }

                var c_op = c_api.TF_FinishOperation(op_desc, status.Handle);

                status.Check(true);

                return(c_op, op_desc);
            }
        }
Exemple #2
0
        /// <summary>
        /// Creates an `Operation`.
        /// </summary>
        /// <param name="node_def">`node_def_pb2.NodeDef`.  `NodeDef` for the `Operation`.</param>
        /// <param name="g">`Graph`. The parent graph.</param>
        /// <param name="inputs">list of `Tensor` objects. The inputs to this `Operation`.</param>
        /// <param name="output_types">list of `DType` objects.</param>
        /// <param name="control_inputs">
        /// list of operations or tensors from which to have a
        /// control dependency.
        /// </param>
        /// <param name="input_types">
        /// List of `DType` objects representing the
        /// types of the tensors accepted by the `Operation`. By default
        /// uses `[x.dtype.base_dtype for x in inputs]`.  Operations that expect
        /// reference-typed inputs must specify these explicitly.
        /// </param>
        /// <param name="original_op"></param>
        /// <param name="op_def"></param>
        public Operation(NodeDef node_def, Graph g, Tensor[] inputs = null, TF_DataType[] output_types = null, ITensorOrOperation[] control_inputs = null, TF_DataType[] input_types = null, string original_op = "", OpDef op_def = null)
        {
            _graph = g;

            // Build the list of control inputs.
            var control_input_ops = new List <Operation>();

            if (control_inputs != null)
            {
                foreach (var c in control_inputs)
                {
                    switch (c)
                    {
                    case Operation c1:
                        control_input_ops.Add(c1);
                        break;

                    default:
                        throw new NotImplementedException($"Control input must be an Operation, a Tensor, or IndexedSlices: {c}");
                    }
                }
            }

            // Dict mapping op name to file and line information for op colocation
            // context managers.
            _control_flow_context = graph._get_control_flow_context();

            // This will be set by self.inputs.
            if (op_def == null)
            {
                op_def = g.GetOpDef(node_def.Op);
            }

            var grouped_inputs = _reconstruct_sequence_inputs(op_def, inputs, node_def.Attr);

            _handle = ops._create_c_op(g, node_def, grouped_inputs, control_input_ops.ToArray());

            // Initialize self._outputs.
            output_types = new TF_DataType[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                output_types[i] = OutputType(i);
            }

            _outputs = new Tensor[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                _outputs[i] = new Tensor(this, i, OutputType(i));
            }

            graph._add_op(this);

            if (_handle != IntPtr.Zero)
            {
                _control_flow_post_processing();
            }
        }
Exemple #3
0
        /// <summary>
        /// Creates an `Operation`.
        /// </summary>
        /// <param name="node_def">`node_def_pb2.NodeDef`.  `NodeDef` for the `Operation`.</param>
        /// <param name="g">`Graph`. The parent graph.</param>
        /// <param name="inputs">list of `Tensor` objects. The inputs to this `Operation`.</param>
        /// <param name="output_types">list of `DType` objects.</param>
        /// <param name="control_inputs">
        /// list of operations or tensors from which to have a
        /// control dependency.
        /// </param>
        /// <param name="input_types">
        /// List of `DType` objects representing the
        /// types of the tensors accepted by the `Operation`. By default
        /// uses `[x.dtype.base_dtype for x in inputs]`.  Operations that expect
        /// reference-typed inputs must specify these explicitly.
        /// </param>
        /// <param name="original_op"></param>
        /// <param name="op_def"></param>
        public Operation(NodeDef node_def, Graph g, List <Tensor> inputs = null, TF_DataType[] output_types = null, Operation[] control_inputs = null, TF_DataType[] input_types = null, string original_op = "", OpDef op_def = null)
        {
            Graph = g;

            // Build the list of control inputs.
            var control_input_ops = new List <Operation>();

            if (control_inputs != null)
            {
                foreach (var c in control_inputs)
                {
                    switch (c)
                    {
                    case Operation c1:
                        control_input_ops.Add(c1);
                        break;

                    default:
                        throw new NotImplementedException($"Control input must be an Operation, a Tensor, or IndexedSlices: {c}");
                    }
                }
            }

            // This will be set by self.inputs.

            _id_value = Graph._next_id();
            if (op_def == null)
            {
                op_def = g.GetOpDef(node_def.Op);
            }

            _handle = ops._create_c_op(g, node_def, inputs, control_input_ops.ToArray());

            // Initialize self._outputs.
            output_types = new TF_DataType[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                output_types[i] = OutputType(i);
            }

            _outputs = new Tensor[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                _outputs[i] = new Tensor(this, i, OutputType(i));
            }

            Graph._add_op(this);

            if (_handle != IntPtr.Zero)
            {
                _control_flow_post_processing();
            }
        }
Exemple #4
0
        /// <summary>
        /// Creates a TF_Operation.
        /// </summary>
        /// <param name="graph">a `Graph`.</param>
        /// <param name="node_def">`node_def_pb2.NodeDef` for the operation to create.</param>
        /// <param name="inputs">
        /// A list of `Tensor`s (corresponding to scalar inputs) and lists of
        /// `Tensor`s (corresponding to sequence inputs, e.g. "int64 * N",
        /// "list(int64)"). The length of the list should be equal to the number of
        /// inputs specified by this operation's op def.
        /// </param>
        /// <param name="control_inputs">A list of `Operation`s to set as control dependencies.</param>
        /// <returns>A wrapped TF_Operation*.</returns>
        public static (IntPtr, OperationDescription) _create_c_op(Graph graph, NodeDef node_def, Tensor[] inputs, Operation[] control_inputs,
                                                                  OpDef op_def = null)
        {
            if (op_def == null)
            {
                op_def = graph.GetOpDef(node_def.Op);
            }

            var input_tensors = _reconstruct_sequence_inputs(op_def, inputs, node_def.Attr);

            var op_desc = graph.NewOperation(node_def.Op, node_def.Name);

            if (!string.IsNullOrEmpty(node_def.Device))
            {
                c_api.TF_SetDevice(op_desc, node_def.Device);
            }

            // Add inputs
            foreach (var op_input in input_tensors)
            {
                if (op_input.IsList)
                {
                    c_api.TF_AddInputList(op_desc, op_input.Select(x => x._as_tf_output()).ToArray(), op_input.Count());
                }
                else if (op_input.Count() == 1)
                {
                    c_api.TF_AddInput(op_desc, op_input[0]._as_tf_output());
                }
            }

            var status = tf.Status;

            // Add control inputs
            foreach (var control_input in control_inputs)
            {
                c_api.TF_AddControlInput(op_desc, control_input);
            }

            // Add attrs
            foreach (var attr in node_def.Attr)
            {
                var bytes = attr.Value.ToByteArray();
                c_api.TF_SetAttrValueProto(op_desc, attr.Key, bytes, proto_len: bytes.Length, status: status.Handle);
                status.Check(true);
            }

            var c_op = op_desc.FinishOperation(status);

            status.Check(true);

            return(c_op, op_desc);
        }
        public Operation(NodeDef node_def, Graph g, List <Tensor> inputs = null, TF_DataType[] output_types = null, object control_inputs = null, TF_DataType[] input_types = null, string original_op = "", OpDef op_def = null)
        {
            Graph = g;

            _id_value = Graph._next_id();
            if (op_def == null)
            {
                op_def = g.GetOpDef(node_def.Op);
            }

            _handle = ops._create_c_op(g, node_def, inputs);

            output_types = new TF_DataType[NumOutputs];

            for (int i = 0; i < NumOutputs; i++)
            {
                output_types[i] = OutputType(i);
            }

            Graph._add_op(this);
        }
Exemple #6
0
 public static OpDef _get_op_def(Graph graph, string type)
 {
     return(graph.GetOpDef(type));
 }
Exemple #7
0
        /*public Operation(Graph g, string opType, string oper_name)
         * {
         *  _graph = g;
         *
         *  var _operDesc = c_api.TF_NewOperation(g, opType, oper_name);
         *  c_api.TF_SetAttrType(_operDesc, "dtype", TF_DataType.TF_INT32);
         *  lock (Locks.ProcessWide)
         *      using (var status = new Status())
         *      {
         *          _handle = c_api.TF_FinishOperation(_operDesc, status);
         *          status.Check(true);
         *      }
         *
         *  // Dict mapping op name to file and line information for op colocation
         *  // context managers.
         *  _control_flow_context = graph._get_control_flow_context();
         * }*/

        /// <summary>
        /// Creates an `Operation`.
        /// </summary>
        /// <param name="node_def">`node_def_pb2.NodeDef`.  `NodeDef` for the `Operation`.</param>
        /// <param name="g">`Graph`. The parent graph.</param>
        /// <param name="inputs">list of `Tensor` objects. The inputs to this `Operation`.</param>
        /// <param name="output_types">list of `DType` objects.</param>
        /// <param name="control_inputs">
        /// list of operations or tensors from which to have a
        /// control dependency.
        /// </param>
        /// <param name="input_types">
        /// List of `DType` objects representing the
        /// types of the tensors accepted by the `Operation`. By default
        /// uses `[x.dtype.base_dtype for x in inputs]`.  Operations that expect
        /// reference-typed inputs must specify these explicitly.
        /// </param>
        /// <param name="original_op"></param>
        /// <param name="op_def"></param>
        public Operation(NodeDef node_def, Graph g, Tensor[] inputs = null, TF_DataType[] output_types = null, ITensorOrOperation[] control_inputs = null, TF_DataType[] input_types = null, string original_op = "", OpDef op_def = null)
        {
            _graph = g;
            // Build the list of control inputs.
            var control_input_ops = new List <Operation>();

            if (control_inputs != null)
            {
                foreach (var c in control_inputs)
                {
                    switch (c)
                    {
                    case Operation c1:
                        control_input_ops.Add(c1);
                        break;

                    case Tensor tensor:
                        control_input_ops.Add(tensor.op);
                        break;

                    // TODO: IndexedSlices don't yet exist, but once they do, this needs to be uncommented
                    //case IndexedSlices islices:
                    //    control_input_ops.Add(islices.op);
                    //    break;
                    default:
                        throw new NotImplementedException($"Control input must be an Operation, a Tensor, or IndexedSlices: {c}");
                    }
                }
            }

            _id_value = _graph._next_id();

            // Dict mapping op name to file and line information for op colocation
            // context managers.
            _control_flow_context = graph._get_control_flow_context();

            // This will be set by self.inputs.
            if (op_def == null)
            {
                op_def = g.GetOpDef(node_def.Op);
            }

            (_handle, OpDesc) = ops._create_c_op(g, node_def, inputs, control_input_ops.ToArray());
            _is_stateful      = op_def.IsStateful;

            // Initialize self._outputs.
            output_types = new TF_DataType[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                output_types[i] = OutputType(i);
            }

            _outputs = new Tensor[NumOutputs];
            for (int i = 0; i < NumOutputs; i++)
            {
                _outputs[i] = new Tensor(this, i, output_types[i]);
            }

            graph._add_op(this);

            if (_handle != IntPtr.Zero)
            {
                _control_flow_post_processing();
            }
        }