A `ControlFlowContext` for nodes inside a TPU computation. The primary role of `TPUReplicateContext` is to mark operators inside a tpu.replicate() computation with the attribute "_tpu_replicate=XYZ", where XYZ is a unique name. We use a `ControlFlowContext` to perform the annotation since
| 181 | |
| 182 | |
| 183 | class TPUReplicateContext(control_flow_ops.XLAControlFlowContext): |
| 184 | """A `ControlFlowContext` for nodes inside a TPU computation. |
| 185 | |
| 186 | The primary role of `TPUReplicateContext` is to mark operators inside a |
| 187 | tpu.replicate() computation with the attribute "_tpu_replicate=XYZ", where XYZ |
| 188 | is a unique name. |
| 189 | |
| 190 | We use a `ControlFlowContext` to perform the annotation since it integrates |
| 191 | with Tensorflow constructs like ResourceVariables. For example, if a |
| 192 | `ResourceVariable` is constructed inside a tpu.replicate() block, the |
| 193 | `ResourceVariable` implementation can use |
| 194 | `with ops.control_dependencies(None)` to build the variable's definition |
| 195 | outside the replicated computation. |
| 196 | """ |
| 197 | |
| 198 | def __init__(self, name, num_replicas, pivot): |
| 199 | """Builds a new TPUReplicateContext. |
| 200 | |
| 201 | Args: |
| 202 | name: a unique name for the context, used to populate the `_tpu_replicate` |
| 203 | attribute. |
| 204 | num_replicas: an integer that gives the number of replicas for the |
| 205 | computation. |
| 206 | pivot: a pivot node. Nodes in the TPUReplicateContext that do not have any |
| 207 | inputs will have a control dependency on the pivot node. This ensures |
| 208 | that nodes are correctly included in any enclosing control flow |
| 209 | contexts. |
| 210 | """ |
| 211 | super(TPUReplicateContext, self).__init__() |
| 212 | self._num_replicas = num_replicas |
| 213 | self._outer_device_function_stack = None |
| 214 | self._oc_dev_fn_stack = None |
| 215 | self._outside_compilation_cluster = None |
| 216 | self._outside_compilation_counter = 0 |
| 217 | self._in_gradient_colocation = None |
| 218 | self._gradient_colocation_stack = [] |
| 219 | self._host_compute_core = [] |
| 220 | self._name = name |
| 221 | self._name_as_bytes = compat.as_bytes(name) |
| 222 | self._unsupported_ops = [] |
| 223 | self._pivot = pivot |
| 224 | self._replicated_vars = {} |
| 225 | |
| 226 | def get_replicated_var_handle(self, name, vars_): |
| 227 | """Returns a variable handle for replicated TPU variable 'var'. |
| 228 | |
| 229 | This is a method used by an experimental replicated variable implementation |
| 230 | and is not intended as a public API. |
| 231 | |
| 232 | Args: |
| 233 | name: The common name of the variable. |
| 234 | vars_: The replicated TPU variables. |
| 235 | |
| 236 | Returns: |
| 237 | The handle of the TPU replicated input node. |
| 238 | """ |
| 239 | handle = self._replicated_vars.get(name) |
| 240 | if handle is not None: |
no outgoing calls
no test coverage detected