示例#1
0
def sync():
    """Synchronize the contents of the Python registry with C++."""
    with _sync_lock:
        p_buffer = c_api.TF_GetAllOpList()
        cpp_op_list = op_def_pb2.OpList()
        cpp_op_list.ParseFromString(c_api.TF_GetBuffer(p_buffer))
        register_op_list(cpp_op_list)
示例#2
0
def make_function_def(name, graph, operations, inputs, outputs):
    """Makes FunctionDef proto and defined function.

  Args:
    name: the function name
    graph: the graph from which to build the function
    operations: the operations in the function body
    inputs: tensors to be used as function arguments
    outputs: tensors to be returned from the function

  Returns:
   fdef: a FunctionDef protocol buffer for the function
   fn: a wrapped TF_Function for the function
  """
    with errors.raise_exception_on_not_ok_status() as status:
        fn = pywrap_tensorflow.TF_GraphToFunction_wrapper(
            graph._c_graph,  # pylint: disable=protected-access
            compat.as_str(name),
            False,
            [o._c_op for o in operations],  # pylint: disable=protected-access
            [t._as_tf_output() for t in inputs],  # pylint: disable=protected-access
            [t._as_tf_output() for t in outputs],  # pylint: disable=protected-access
            [],
            None,
            compat.as_str(""),
            status)
    # TODO(apassos) avoid creating a FunctionDef (specially to grab the signature,
    # but also in general it's nice not to depend on it.
    with c_api_util.tf_buffer() as buffer_:
        with errors.raise_exception_on_not_ok_status() as status:
            pywrap_tensorflow.TF_FunctionToFunctionDef(fn, buffer_, status)
        proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
    fdef = function_pb2.FunctionDef()
    fdef.ParseFromString(compat.as_bytes(proto_data))
    return fdef, fn
示例#3
0
def stop():
  """Stop current profiling session and return its result.

  Returns:
    A binary string of tensorflow.tpu.Trace. User can write the string
    to file for offline analysis by tensorboard.

  Raises:
    AssertionError: If there is no active profiling session.
  """
  global _profiler
  global _run_num
  if _profiler is None:
    raise AssertionError('Cannot stop profiling. No profiler is running.')
  with c_api_util.tf_buffer() as buffer_:
    pywrap_tensorflow.TFE_ProfilerSerializeToString(
        context.context()._handle,  # pylint: disable=protected-access
        _profiler,
        buffer_)
    result = pywrap_tensorflow.TF_GetBuffer(buffer_)
  with _profiler_lock:
    pywrap_tensorflow.TFE_DeleteProfiler(_profiler)
    _profiler = None
    _run_num += 1
  return result
示例#4
0
 def value(self):
     """Retrieves the current value."""
     with c_api_util.tf_buffer() as buffer_:
         pywrap_tensorflow.TFE_MonitoringStringGaugeCellValue(
             self._cell, buffer_)
         value = pywrap_tensorflow.TF_GetBuffer(buffer_).decode('utf-8')
     return value
def stop():
    """Stop current profiling session and return its result.

  Returns:
    A binary string of tensorflow.tpu.Trace. User can write the string
    to file for offline analysis by tensorboard.

  Raises:
    ProfilerNotRunningError: If there is no active profiling session.
  """
    global _profiler
    global _run_num
    with _profiler_lock:
        if _profiler is None:
            raise ProfilerNotRunningError(
                'Cannot stop profiling. No profiler is running.')
        if context.default_execution_mode == context.EAGER_MODE:
            context.context().executor.wait()
        with c_api_util.tf_buffer() as buffer_:
            pywrap_tensorflow.TFE_ProfilerSerializeToString(_profiler, buffer_)
            result = pywrap_tensorflow.TF_GetBuffer(buffer_)
        pywrap_tensorflow.TFE_DeleteProfiler(_profiler)
        _profiler = None
        _run_num += 1
    return result
示例#6
0
def function_def_from_tf_function(c_func):
    """Converts a SWIG-wrapped TF_Function* to a FunctionDef proto."""
    with c_api_util.tf_buffer() as buf:
        c_api.TF_FunctionToFunctionDef(c_func, buf)
        data = c_api.TF_GetBuffer(buf)
    fdef = function_pb2.FunctionDef()
    fdef.ParseFromString(compat.as_bytes(data))
    return fdef
示例#7
0
 def get_api_def(self, op_name):
     api_def_proto = api_def_pb2.ApiDef()
     buf = c_api.TF_ApiDefMapGet(self._api_def_map, op_name, len(op_name))
     try:
         api_def_proto.ParseFromString(c_api.TF_GetBuffer(buf))
     finally:
         c_api.TF_DeleteBuffer(buf)
     return api_def_proto
示例#8
0
文件: kernels.py 项目: Harryi0/tinyML
def get_all_registered_kernels():
    """Returns a KernelList proto of all registered kernels.
  """
    buf = c_api.TF_GetAllRegisteredKernels()
    data = c_api.TF_GetBuffer(buf)
    kernel_list = kernel_def_pb2.KernelList()
    kernel_list.ParseFromString(compat.as_bytes(data))
    return kernel_list
示例#9
0
 def definition(self):
     """Function definition proto."""
     self._create_definition_if_needed()
     if self._c_func:
         with c_api_util.tf_buffer() as buf:
             c_api.TF_FunctionToFunctionDef(self._c_func.func, buf)
             fdef = function_pb2.FunctionDef()
             proto_data = c_api.TF_GetBuffer(buf)
             fdef.ParseFromString(compat.as_bytes(proto_data))
         return fdef
     return self._definition
示例#10
0
文件: kernels.py 项目: Harryi0/tinyML
def get_registered_kernels_for_op(name):
    """Returns a KernelList proto of registered kernels for a given op.

  Args:
    name: A string representing the name of the op whose kernels to retrieve.
  """
    buf = c_api.TF_GetRegisteredKernelsForOp(name)
    data = c_api.TF_GetBuffer(buf)
    kernel_list = kernel_def_pb2.KernelList()
    kernel_list.ParseFromString(compat.as_bytes(data))
    return kernel_list
示例#11
0
  def sync():
    p_buffer = c_api.TF_GetAllOpList()
    cpp_op_list = op_def_pb2.OpList()
    cpp_op_list.ParseFromString(c_api.TF_GetBuffer(p_buffer))

    registered_ops = op_def_registry.get_registered_ops()
    for op_def in cpp_op_list.op:
      # If an OpList is registered from a gen_*_ops.py, it does not any
      # descriptions. Strip them here as well to satisfy validation in
      # register_op_list.
      _remove_non_deprecated_descriptions(op_def)
      registered_ops[op_def.name] = op_def
示例#12
0
  def value(self):
    """Retrieves the current distribution of samples.

    Returns:
      A HistogramProto describing the distribution of samples.
    """
    with c_api_util.tf_buffer() as buffer_:
      pywrap_tensorflow.TFE_MonitoringSamplerCellValue(self._cell, buffer_)
      proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
    histogram_proto = summary_pb2.HistogramProto()
    histogram_proto.ParseFromString(compat.as_bytes(proto_data))
    return histogram_proto
示例#13
0
def sync():
  """Synchronize the contents of the Python registry with C++."""
  with _sync_lock:
    p_buffer = c_api.TF_GetAllOpList()
    cpp_op_list = op_def_pb2.OpList()
    cpp_op_list.ParseFromString(c_api.TF_GetBuffer(p_buffer))
    for op_def in cpp_op_list.op:
      # If an OpList is registered from a gen_*_ops.py, it does not any
      # descriptions. Strip them here as well to satisfy validation in
      # register_op_list.
      _remove_non_deprecated_descriptions(op_def)
      _registered_ops[op_def.name] = op_def
示例#14
0
 def definition(self):
   """Function definition proto."""
   self._create_definition_if_needed()
   if self._c_func:
     with c_api_util.tf_buffer() as buf:
       with errors.raise_exception_on_not_ok_status() as status:
         c_api.TF_FunctionToFunctionDef(self._c_func, buf, status)
       fdef = function_pb2.FunctionDef()
       proto_data = c_api.TF_GetBuffer(buf)
       fdef.ParseFromString(compat.as_bytes(proto_data))
     return fdef
   return self._definition
示例#15
0
    def __init__(self):
        op_def_proto = op_def_pb2.OpList()
        buf = c_api.TF_GetAllOpList()
        try:
            op_def_proto.ParseFromString(c_api.TF_GetBuffer(buf))
            self._api_def_map = c_api.TF_NewApiDefMap(buf)
        finally:
            c_api.TF_DeleteBuffer(buf)

        self._op_per_name = {}
        for op in op_def_proto.op:
            self._op_per_name[op.name] = op
示例#16
0
    def __hook__(self, session, handle, args, status, run_metadata_ptr):
        assert run_metadata_ptr is None  # TODO(levosos): handle this

        run_metadata_ptr = tf_c_api.TF_NewBuffer()
        result = self.__original__(session, handle, args, status,
                                   run_metadata_ptr)

        proto = tf_c_api.TF_GetBuffer(run_metadata_ptr)
        tf_c_api.TF_DeleteBuffer(run_metadata_ptr)

        run_metadata = tensorflow.RunMetadata()
        run_metadata.ParseFromString(compat.as_bytes(proto))

        self._update(run_metadata)

        return result
示例#17
0
 def definition(self):
   """Function definition proto."""
   self._create_definition_if_needed()
   if self._c_func:
     with c_api_util.tf_buffer() as buf:
       c_api.TF_FunctionToFunctionDef(self._c_func.func, buf)
       fdef = function_pb2.FunctionDef()
       proto_data = c_api.TF_GetBuffer(buf)
       fdef.ParseFromString(compat.as_bytes(proto_data))
       with ops.init_scope():
         if context.executing_eagerly():
           context.add_function(self._c_func.func)
           self._function_deleter = _DefinedFunctionDeleter(
               fdef.signature.name)
     return fdef
   return self._definition
示例#18
0
    def __init__(self, name, graph, operations, inputs, outputs, attrs):
        """Initializes an eager defined function.

    Args:
      name: str, the name for the created function.
      graph: Graph, the graph containing the operations in the function
      operations: list of Operation; the subset of operations in the graph
        which will be in the function
      inputs: the tensors in the graph to be used as inputs to the function
      outputs: the tensors in the graph which will be outputs to the function
      attrs: dict mapping names of attributes to their AttrValue values
    """
        fn = pywrap_tensorflow.TF_GraphToFunction_wrapper(
            graph._c_graph,  # pylint: disable=protected-access
            compat.as_str(name),
            False,
            [o._c_op for o in operations],  # pylint: disable=protected-access
            [t._as_tf_output() for t in inputs],  # pylint: disable=protected-access
            [t._as_tf_output() for t in outputs],  # pylint: disable=protected-access
            [],
            None,
            compat.as_str(""))

        for name, attr_value in attrs.items():
            serialized = attr_value.SerializeToString()
            # TODO(iga): this creates and deletes a new TF_Status for every attr.
            # It might be worth creating a convenient way to re-use status.
            pywrap_tensorflow.TF_FunctionSetAttrValueProto(
                fn, compat.as_str(name), serialized)

        # TODO(apassos) avoid creating a FunctionDef (specially to grab the
        # signature, but also in general it's nice not to depend on it.
        with c_api_util.tf_buffer() as buffer_:
            pywrap_tensorflow.TF_FunctionToFunctionDef(fn, buffer_)
            proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
        function_def = function_pb2.FunctionDef()
        function_def.ParseFromString(compat.as_bytes(proto_data))
        if context.executing_eagerly():
            _register(fn)
        self.definition = function_def
        self.name = function_def.signature.name
        self.signature = function_def.signature
        self.grad_func_name = None
        self.python_grad_func = None
        self._c_func = c_api_util.ScopedTFFunction(fn)
        self._grad_func = None
示例#19
0
    def export_run_metadata(self):
        """Returns a RunMetadata proto with accumulated information.

    The returned protocol buffer contains information since the most recent call
    to either enable_run_metadata or export_run_metadata.

    Returns:
      A RunMetadata protocol buffer.
    """
        with c_api_util.tf_buffer() as buffer_:
            with errors.raise_exception_on_not_ok_status() as status:
                pywrap_tensorflow.TFE_ContextExportRunMetadata(
                    self._context_handle, buffer_, status)
            proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
        run_metadata = config_pb2.RunMetadata()
        run_metadata.ParseFromString(compat.as_bytes(proto_data))
        return run_metadata
示例#20
0
    def export_run_metadata(self):
        """Returns a RunMetadata proto with accumulated information.

    The returned protocol buffer contains information since the most recent call
    to either enable_run_metadata or export_run_metadata.

    Returns:
      A RunMetadata protocol buffer. Or None if not enabled.
    """
        if not self._context_handle:
            return None
        with c_api_util.tf_buffer() as buffer_:
            pywrap_tensorflow.TFE_ContextExportRunMetadata(
                self._context_handle, buffer_)
            proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
        run_metadata = config_pb2.RunMetadata()
        run_metadata.ParseFromString(compat.as_bytes(proto_data))
        return run_metadata
示例#21
0
def register_ops_if_needed(graph_ops):
    """Register graph ops absent in op_def_registry, if present in c++ registry.

  Args:
    graph_ops: set with graph op names to register.

  Raises:
    RuntimeError: if `graph_ops` contains ops that are not in either python or
      c++ registry.
  """
    missing_ops = graph_ops - set(op_def_registry.get_registered_ops().keys())

    if not missing_ops:
        return

    p_buffer = c_api.TF_GetAllOpList()
    cpp_op_list = op_def_pb2.OpList()
    cpp_op_list.ParseFromString(c_api.TF_GetBuffer(p_buffer))
    cpp_registry_ops = {op.name: op for op in cpp_op_list.op}

    missing_op_list = op_def_pb2.OpList()
    for missing_op in missing_ops:
        if missing_op not in cpp_registry_ops:
            tf.logging.info(
                "Op %s is missing from both the python and C++ registry.",
                missing_op)
        else:
            missing_op_list.op.extend([cpp_registry_ops[missing_op]])
            tf.logging.info(
                "Adding op %s from c++ registry to python registry.",
                missing_op)

    op_def_registry.register_op_list(missing_op_list)

    # Note: Only raise missing op ValueError after trying to load ops.
    # This allows the test to exercise all the calls into TensorFlow
    # without having to write a C + python test.
    if not missing_ops <= set(cpp_registry_ops.keys()):
        raise RuntimeError(
            "Graph ops missing from the python registry (%s) are also absent from "
            "the c++ registry." %
            missing_ops.difference(set(cpp_registry_ops.keys())))
示例#22
0
    def __init__(self, name, graph, operations, inputs, outputs):
        """Initializes an eager defined function.

    Args:
      name: str, the name for the created function.
      graph: Graph, the graph containing the operations in the function
      operations: list of Operation; the subset of operations in the graph
        which will be in the function
      inputs: the tensors in the graph to be used as inputs to the function
      outputs: the tensors in the graph which will be outputs to the function
    """
        with errors.raise_exception_on_not_ok_status() as status:
            fn = pywrap_tensorflow.TF_GraphToFunction_wrapper(
                graph._c_graph,  # pylint: disable=protected-access
                compat.as_str(name),
                False,
                [o._c_op for o in operations],  # pylint: disable=protected-access
                [t._as_tf_output() for t in inputs],  # pylint: disable=protected-access
                [t._as_tf_output() for t in outputs],  # pylint: disable=protected-access
                [],
                None,
                compat.as_str(""),
                status)
        # TODO(apassos) avoid creating a FunctionDef (specially to grab the
        # signature, but also in general it's nice not to depend on it.
        with c_api_util.tf_buffer() as buffer_:
            with errors.raise_exception_on_not_ok_status() as status:
                pywrap_tensorflow.TF_FunctionToFunctionDef(fn, buffer_, status)
            proto_data = pywrap_tensorflow.TF_GetBuffer(buffer_)
        function_def = function_pb2.FunctionDef()
        function_def.ParseFromString(compat.as_bytes(proto_data))
        if context.in_eager_mode():
            _register(fn)
        self.definition = function_def
        self.name = function_def.signature.name
        self.signature = function_def.signature
        self.grad_func_name = None
        self.python_grad_func = None
        self._c_func = fn
        self._grad_func = None
示例#23
0
def monitor(service_addr,
            duration_ms,
            monitoring_level=1,
            display_timestamp=False):
    """Sends grpc requests to profiler server to perform on-demand monitoring.

  This method will block caller thread until receives monitoring result.

  Args:
    service_addr: Address of profiler service e.g. localhost:6009.
    duration_ms: Duration of tracing or monitoring in ms.
    monitoring_level: Choose a monitoring level between 1 and 2 to monitor your
      job. Level 2 is more verbose than level 1 and shows more metrics.
    display_timestamp: Set to true to display timestamp in monitoring result.

  Returns:
    A string of monitoring output.
  """
    with c_api_util.tf_buffer() as buffer_:
        pywrap_tensorflow.TFE_ProfilerClientMonitor(service_addr, duration_ms,
                                                    monitoring_level,
                                                    display_timestamp, buffer_)
        return pywrap_tensorflow.TF_GetBuffer(buffer_)
示例#24
0
    def run(self, fetches, feed_dict=None, options=None, run_outputs=None):
        """Runs the operations and evaluates the tensors in `fetches`.

    This method runs one "step" of TensorFlow computation, by
    running the necessary graph fragment to execute every `Operation`
    and evaluate every `Tensor` in `fetches`, substituting the values in
    `feed_dict` for the corresponding input values.

    The `fetches` argument may be a list of graph elements or a single
    graph element, and these determine the return value of this
    method. A graph element can be one of the following types:

    * If the *i*th element of `fetches` is an
      [`Operation`](../../api_docs/python/framework.md#Operation), the *i*th
      return value will be `None`.
    * If the *i*th element of `fetches` is a
      [`Tensor`](../../api_docs/python/framework.md#Tensor), the *i*th return
      value will be a numpy ndarray containing the value of that tensor.
    * If the *i*th element of `fetches` is a
      [`SparseTensor`](../../api_docs/python/sparse_ops.md#SparseTensor),
      the *i*th return value will be a
      [`SparseTensorValue`](../../api_docs/python/sparse_ops.md#SparseTensorValue)
      containing the value of that sparse tensor.

    The optional `feed_dict` argument allows the caller to override
    the value of tensors in the graph. Each key in `feed_dict` can be
    one of the following types:

    * If the key is a [`Tensor`](../../api_docs/python/framework.md#Tensor), the
      value may be a Python scalar, string, list, or numpy ndarray
      that can be converted to the same `dtype` as that
      tensor. Additionally, if the key is a
      [placeholder](../../api_docs/python/io_ops.md#placeholder), the shape of
      the value will be checked for compatibility with the placeholder.
    * If the key is a
      [`SparseTensor`](../../api_docs/python/sparse_ops.md#SparseTensor),
      the value should be a
      [`SparseTensorValue`](../../api_docs/python/sparse_ops.md#SparseTensorValue).

    The optional `options` argument expects a [`RunOptions`] proto. The options
    allow controlling the behavior of this particular step (e.g. turning tracing
    on).

    The optional `run_outputs` argument expects a [`RunOutputs`] proto. When
    appropriate, the non-Tensor output of this step will be collected there. For
    example, when users turn on tracing in `options`, the profiled info will be
    collected into this argument and passed back.

    Args:
      fetches: A single graph element, or a list of graph elements
        (described above).
      feed_dict: A dictionary that maps graph elements to values
        (described above).
      options: A [`RunOptions`] protocol buffer
      run_outputs: A [`RunOutputs`] protocol buffer

    Returns:
      Either a single value if `fetches` is a single graph element, or
      a list of values if `fetches` is a list (described above).

    Raises:
      RuntimeError: If this `Session` is in an invalid state (e.g. has been
        closed).
      TypeError: If `fetches` or `feed_dict` keys are of an inappropriate type.
      ValueError: If `fetches` or `feed_dict` keys are invalid or refer to a
        `Tensor` that doesn't exist.
    """
        run_outputs_ptr = tf_session.TF_NewBuffer()
        if options:
            options_ptr = tf_session.TF_NewBufferFromString(
                compat.as_bytes(options.SerializeToString()))
        else:
            options_ptr = None

        try:
            result = self._run(None, fetches, feed_dict, options_ptr,
                               run_outputs_ptr)
            if run_outputs:
                proto_data = tf_session.TF_GetBuffer(run_outputs_ptr)
                run_outputs.ParseFromString(compat.as_bytes(proto_data))
        finally:
            tf_session.TF_DeleteBuffer(run_outputs_ptr)
            if options:
                tf_session.TF_DeleteBuffer(options_ptr)
        return result
示例#25
0
  def run(self, fetches, feed_dict=None, options=None, run_metadata=None):
    """Runs operations and evaluates tensors in `fetches`.

    This method runs one "step" of TensorFlow computation, by
    running the necessary graph fragment to execute every `Operation`
    and evaluate every `Tensor` in `fetches`, substituting the values in
    `feed_dict` for the corresponding input values.

    The `fetches` argument may be a single graph element, or an arbitrarily
    nested list, tuple, namedtuple, dict, or OrderedDict containing graph
    elements at its leaves.  A graph element can be one of the following types:

    * An [`Operation`](../../api_docs/python/framework.md#Operation).
      The corresponding fetched value will be `None`.
    * A [`Tensor`](../../api_docs/python/framework.md#Tensor).
      The corresponding fetched value will be a numpy ndarray containing the
      value of that tensor.
    * A [`SparseTensor`](../../api_docs/python/sparse_ops.md#SparseTensor).
      The corresponding fetched value will be a
      [`SparseTensorValue`](../../api_docs/python/sparse_ops.md#SparseTensorValue)
      containing the value of that sparse tensor.
    * A `get_tensor_handle` op.  The corresponding fetched value will be a
      numpy ndarray containing the handle of that tensor.
    * A `string` which is the name of a tensor or operation in the graph.

    The value returned by `run()` has the same shape as the `fetches` argument,
    where the leaves are replaced by the corresponding values returned by
    TensorFlow.

    Example:

    ```python
       a = tf.constant([10, 20])
       b = tf.constant([1.0, 2.0])
       # 'fetches' can be a singleton
       v = session.run(a)
       # v is the numpy array [10, 20]
       # 'fetches' can be a list.
       v = session.run([a, b])
       # v a Python list with 2 numpy arrays: the numpy array [10, 20] and the
       # 1-D array [1.0, 2.0]
       # 'fetches' can be arbitrary lists, tuples, namedtuple, dicts:
       MyData = collections.namedtuple('MyData', ['a', 'b'])
       v = session.run({'k1': MyData(a, b), 'k2': [b, a]})
       # v is a dict with
       # v['k1'] is a MyData namedtuple with 'a' the numpy array [10, 20] and
       # 'b' the numpy array [1.0, 2.0]
       # v['k2'] is a list with the numpy array [1.0, 2.0] and the numpy array
       # [10, 20].
    ```

    The optional `feed_dict` argument allows the caller to override
    the value of tensors in the graph. Each key in `feed_dict` can be
    one of the following types:

    * If the key is a [`Tensor`](../../api_docs/python/framework.md#Tensor), the
      value may be a Python scalar, string, list, or numpy ndarray
      that can be converted to the same `dtype` as that
      tensor. Additionally, if the key is a
      [placeholder](../../api_docs/python/io_ops.md#placeholder), the shape of
      the value will be checked for compatibility with the placeholder.
    * If the key is a
      [`SparseTensor`](../../api_docs/python/sparse_ops.md#SparseTensor),
      the value should be a
      [`SparseTensorValue`](../../api_docs/python/sparse_ops.md#SparseTensorValue).
    * If the key is a nested tuple of `Tensor`s or `SparseTensor`s, the value
      should be a nested tuple with the same structure that maps to their
      corresponding values as above.

    Each value in `feed_dict` must be convertible to a numpy array of the dtype
    of the corresponding key.

    The optional `options` argument expects a [`RunOptions`] proto. The options
    allow controlling the behavior of this particular step (e.g. turning tracing
    on).

    The optional `run_metadata` argument expects a [`RunMetadata`] proto. When
    appropriate, the non-Tensor output of this step will be collected there. For
    example, when users turn on tracing in `options`, the profiled info will be
    collected into this argument and passed back.

    Args:
      fetches: A single graph element, a list of graph elements,
        or a dictionary whose values are graph elements or lists of graph
        elements (described above).
      feed_dict: A dictionary that maps graph elements to values
        (described above).
      options: A [`RunOptions`] protocol buffer
      run_metadata: A [`RunMetadata`] protocol buffer

    Returns:
      Either a single value if `fetches` is a single graph element, or
      a list of values if `fetches` is a list, or a dictionary with the
      same keys as `fetches` if that is a dictionary (described above).

    Raises:
      RuntimeError: If this `Session` is in an invalid state (e.g. has been
        closed).
      TypeError: If `fetches` or `feed_dict` keys are of an inappropriate type.
      ValueError: If `fetches` or `feed_dict` keys are invalid or refer to a
        `Tensor` that doesn't exist.
    """
    run_metadata_ptr = tf_session.TF_NewBuffer()
    if options:
      options_ptr = tf_session.TF_NewBufferFromString(
          compat.as_bytes(options.SerializeToString()))
    else:
      options_ptr = None

    try:
      result = self._run(None, fetches, feed_dict, options_ptr,
                         run_metadata_ptr)
      if run_metadata:
        proto_data = tf_session.TF_GetBuffer(run_metadata_ptr)
        run_metadata.ParseFromString(compat.as_bytes(proto_data))
    finally:
      tf_session.TF_DeleteBuffer(run_metadata_ptr)
      if options:
        tf_session.TF_DeleteBuffer(options_ptr)
    return result