You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

Graph.Operation.cs 6.9 kB

6 years ago
6 years ago
6 years ago
4 years ago
4 years ago
4 years ago
6 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /*****************************************************************************
  2. Copyright 2018 The TensorFlow.NET Authors. All Rights Reserved.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ******************************************************************************/
  13. using System;
  14. using System.Collections.Generic;
  15. using System.Linq;
  16. using System.Runtime.InteropServices;
  17. using static Tensorflow.Binding;
  18. namespace Tensorflow
  19. {
  20. public partial class Graph
  21. {
  22. public OpDef GetOpDef(string type)
  23. => op_def_registry.GetOpDef(type);
  24. public OperationDescription NewOperation(string opType, string opName)
  25. {
  26. return c_api.TF_NewOperation(_handle, opType, opName);
  27. }
  28. public Operation[] ReturnOperations(SafeImportGraphDefResultsHandle results)
  29. {
  30. TF_Operation return_oper_handle = new TF_Operation();
  31. int num_return_opers = 0;
  32. c_api.TF_ImportGraphDefResultsReturnOperations(results, ref num_return_opers, ref return_oper_handle);
  33. Operation[] return_opers = new Operation[num_return_opers];
  34. var tf_op_size = Marshal.SizeOf<TF_Operation>();
  35. for (int i = 0; i < num_return_opers; i++)
  36. {
  37. unsafe
  38. {
  39. var handle = return_oper_handle.node + tf_op_size * i;
  40. return_opers[i] = new Operation(*(IntPtr*)handle);
  41. }
  42. }
  43. return return_opers;
  44. }
  45. /// <summary>
  46. /// Get operation with given <paramref name="operName"/>
  47. /// </summary>
  48. /// <exception cref="ValueError">When <paramref name="operName"/> is not found current graph.</exception>
  49. /// <exception cref="RuntimeError">When tf.get_default_graph() is not current graph.</exception>
  50. /// <example>
  51. /// graph.GetOperationByName("CustomInputName");
  52. /// </example>
  53. public Operation OperationByName(string operName)
  54. {
  55. if (operName == null)
  56. throw new ArgumentNullException(nameof(operName));
  57. var handle = c_api.TF_GraphOperationByName(_handle, operName);
  58. if (handle == IntPtr.Zero)
  59. throw new ValueError($"Could not find operation \"{operName}\" inside graph \"{_graph_key}\".");
  60. /*var defaultKey = tf.get_default_graph().graph_key;
  61. if (tf.get_default_graph().GetType().Name == "Graph" && graph_key != defaultKey)
  62. {
  63. throw new RuntimeError($"Current graph is not default graph. Default Graph Key: {defaultKey}, Current Graph Key: {graph_key}");
  64. }*/
  65. return new Operation(handle, g: this);
  66. }
  67. public ITensorOrOperation[] get_operations()
  68. {
  69. return _nodes_by_name.Values.ToArray();
  70. }
  71. /// <summary>
  72. /// Returns the `Operation` with the given `name`.
  73. ///
  74. /// This method may be called concurrently from multiple threads.
  75. /// </summary>
  76. /// <param name="name">The name of the `Operation` to return.</param>
  77. public Operation get_operation_by_name(string name)
  78. => as_graph_element(name, allow_tensor: false, allow_operation: true) as Operation;
  79. public ITensorOrOperation _get_operation_by_name_unsafe(string name)
  80. {
  81. return _nodes_by_name.TryGetValue(name, out var val) ? val : null;
  82. }
  83. public ITensorOrOperation _get_operation_by_tf_operation(IntPtr tf_oper)
  84. {
  85. var op_name = Marshal.PtrToStringAnsi(c_api.TF_OperationName(tf_oper));
  86. return _get_operation_by_name_unsafe(op_name);
  87. }
  88. /// <summary>
  89. /// Creates an `Operation` in this graph from the supplied TF_Operation.
  90. ///
  91. /// This method is like create_op() except the new Operation is constructed
  92. /// using `c_op`. The returned Operation will have `c_op` as its _c_op
  93. /// field.This is used to create Operation objects around TF_Operations created
  94. /// indirectly by the C API(e.g.by TF_ImportGraphDef, TF_FinishWhile).
  95. ///
  96. /// This function does not call Operation._control_flow_post_processing or
  97. /// Graph._control_dependencies_for_inputs (since the inputs may not be
  98. /// available yet). The caller is responsible for calling these methods.
  99. /// </summary>
  100. /// <param name="c_op">a wrapped TF_Operation</param>
  101. /// <param name="compute_device">(Optional.) If True, device functions will be executed
  102. /// to compute the device property of the Operation.</param>
  103. /// <returns>An `Operation` object.</returns>
  104. public Operation _create_op_from_tf_operation(IntPtr c_op, bool compute_device = true, OperationDescription desc = null)
  105. {
  106. var ret = new Operation(c_op, this);
  107. _add_op(ret);
  108. var name_key = ret.name.ToLower();
  109. if (!_names_in_use.ContainsKey(name_key))
  110. _names_in_use[name_key] = 1;
  111. _create_op_helper(ret, compute_device: compute_device);
  112. return ret;
  113. }
  114. /// <summary>
  115. /// Creates `Operations` in this graph for any new TF_Operations.
  116. ///
  117. /// This is useful for when TF_Operations are indirectly created by the C API
  118. /// outside of the Operation constructor (e.g. by TF_ImportGraphDef,
  119. /// TF_FinishWhile). This ensures there are corresponding Operations for all
  120. /// TF_Operations in the underlying TF_Graph.
  121. /// </summary>
  122. /// <param name="compute_devices"></param>
  123. /// <returns></returns>
  124. public IEnumerable<Operation> _add_new_tf_operations(bool compute_devices = true)
  125. {
  126. var new_ops = c_api_util.new_tf_operations(this)
  127. .Select(c_op => _create_op_from_tf_operation(c_op, compute_device: compute_devices))
  128. .ToArray();
  129. foreach (var op in new_ops)
  130. {
  131. var new_control_inputs = _control_dependencies_for_inputs(op.inputs)
  132. .Select(x => x as Operation)
  133. .ToArray();
  134. op._add_control_inputs(new_control_inputs);
  135. op._control_flow_post_processing();
  136. }
  137. return new_ops;
  138. }
  139. }
  140. }