/// <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); } }
/// <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 _create_c_op <T>(Graph graph, NodeDef node_def, T[] inputs, Operation[] control_inputs) { 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 inputs) { if (op_input is Tensor[] op_inputs) { c_api.TF_AddInputList(op_desc, op_inputs.Select(x => x._as_tf_output()).ToArray(), op_inputs.Length); } else if (op_input is Tensor op_input1) { c_api.TF_AddInput(op_desc, op_input1._as_tf_output()); } else { throw new NotImplementedException("_create_c_op"); } } using (var status = new 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); status.Check(true); Marshal.FreeHGlobal(protoHandle); } var c_op = c_api.TF_FinishOperation(op_desc, status); status.Check(true); return(c_op); } } }
/// <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 _create_c_op <T>(Graph graph, NodeDef node_def, T[] inputs, Operation[] control_inputs) { var op_desc = graph.NewOperation(node_def.Op, node_def.Name); // Add inputs foreach (var op_input in inputs) { if (op_input is Tensor[] op_inputs) { c_api.TF_AddInputList(op_desc, op_inputs.Select(x => x._as_tf_output()).ToArray(), op_inputs.Length); } else if (op_input is Tensor op_input1) { if (op_input1.op == null) { c_api.TF_AddInput(op_desc, new TF_Output(op_desc, 0)); } else { c_api.TF_AddInput(op_desc, op_input1._as_tf_output()); } } else { throw new NotImplementedException("_create_c_op"); } } var status = new 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(); var proto = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, proto, bytes.Length); uint len = (uint)bytes.Length; c_api.TF_SetAttrValueProto(op_desc, attr.Key, proto, proto_len: len, status: status); status.Check(true); } var c_op = c_api.TF_FinishOperation(op_desc, status); status.Check(true); return(c_op); }
/// <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); }
/// <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 _create_c_op(Graph graph, NodeDef node_def, List <Tensor> inputs, Operation[] control_inputs) { var op_desc = graph.NewOperation(node_def.Op, node_def.Name); // Add inputs if (inputs != null) { foreach (var op_input in inputs) { bool isList = false; if (!isList) { c_api.TF_AddInput(op_desc, op_input._as_tf_output()); } else { c_api.TF_AddInputList(op_desc, inputs.Select(x => x._as_tf_output()).ToArray(), inputs.Count); } } } var status = new 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(); var proto = Marshal.AllocHGlobal(bytes.Length); Marshal.Copy(bytes, 0, proto, bytes.Length); c_api.TF_SetAttrValueProto(op_desc, attr.Key, proto, proto_len: (uint)bytes.Length, status: status); status.Check(true); } var c_op = c_api.TF_FinishOperation(op_desc, status); status.Check(true); return(c_op); }