Builds graph operators that compiles and symbolically executes computation. Args: computation: A Python function that builds the computation to compile and execute. inputs: A list of inputs or `None` (equivalent to an empty list). Each input can be a nested structure containin
(computation, inputs=None)
| 292 | |
| 293 | |
| 294 | def _compile_internal(computation, inputs=None): |
| 295 | """Builds graph operators that compiles and symbolically executes computation. |
| 296 | |
| 297 | Args: |
| 298 | computation: A Python function that builds the computation to compile and |
| 299 | execute. |
| 300 | inputs: A list of inputs or `None` (equivalent to an empty list). Each input |
| 301 | can be a nested structure containing values that are convertible to |
| 302 | tensors. Note that passing an N-dimension list of compatible values will |
| 303 | result in a N-dimension list of scalar tensors rather than a single Rank-N |
| 304 | tensors. If you need different behavior, convert part of inputs to tensors |
| 305 | with `tf.convert_to_tensor`. |
| 306 | |
| 307 | Returns: |
| 308 | Same data structure as if computation(*inputs) is called directly with some |
| 309 | exceptions for correctness. Exceptions include: 1) None output 2) Single |
| 310 | value output 3) Operation-only outputs |
| 311 | Raises: |
| 312 | ValueError: If any element in computation outputs is neither an operations |
| 313 | or a value that can be converted to tensor. |
| 314 | ValueError: If computation outputs is non-flat and contains any Operations. |
| 315 | TypeError: If `inputs` is not a list or tuple. |
| 316 | """ |
| 317 | if inputs is None: |
| 318 | inputs = [] |
| 319 | |
| 320 | if not isinstance(inputs, collections.Sequence): |
| 321 | raise TypeError('inputs must be a list') |
| 322 | |
| 323 | # Flatten inputs. |
| 324 | flat_inputs = nest.flatten(inputs) |
| 325 | # Converts inputs to Tensors. |
| 326 | flat_inputs = [ops.convert_to_tensor(x) for x in flat_inputs] |
| 327 | |
| 328 | cluster_name = ops.get_default_graph().unique_name('cluster') |
| 329 | pivot = control_flow_ops.no_op(name=cluster_name + '/pivot') |
| 330 | context = XLACompileContext(name=cluster_name, pivot=pivot) |
| 331 | try: |
| 332 | context.Enter() |
| 333 | |
| 334 | # Add identity ops so even unused inputs are 'consumed' by the |
| 335 | # computation. |
| 336 | flat_inputs = [ |
| 337 | array_ops.identity(x, name='input_{}'.format(i)) |
| 338 | for i, x in enumerate(flat_inputs) |
| 339 | ] |
| 340 | |
| 341 | # Re-pack flat_inputs in same structure as 'inputs'. |
| 342 | computation_inputs = nest.pack_sequence_as( |
| 343 | structure=inputs, flat_sequence=flat_inputs) |
| 344 | |
| 345 | # Only resource variables work inside an XLA computation, so turn on |
| 346 | # resource variables for the computation. |
| 347 | vscope = variable_scope.get_variable_scope() |
| 348 | saved_use_resource = vscope.use_resource |
| 349 | vscope.set_use_resource(True) |
| 350 | |
| 351 | with _disable_summary_context(): |
no test coverage detected