Data-parallel training in "replicated" mode, where each GPU contains a replicate of the whole model. It will build one tower on each GPU under its own variable scope. Each gradient update is averaged or summed across or GPUs through NCCL. It is an equivalent of ``--variable_upd
| 194 | |
| 195 | |
| 196 | class SyncMultiGPUReplicatedBuilder(DataParallelBuilder): |
| 197 | """ |
| 198 | Data-parallel training in "replicated" mode, |
| 199 | where each GPU contains a replicate of the whole model. |
| 200 | It will build one tower on each GPU under its own variable scope. |
| 201 | Each gradient update is averaged or summed across or GPUs through NCCL. |
| 202 | |
| 203 | It is an equivalent of ``--variable_update=replicated`` in |
| 204 | `tensorflow/benchmarks <https://github.com/tensorflow/benchmarks>`_. |
| 205 | """ |
| 206 | |
| 207 | def __init__(self, towers, average, mode): |
| 208 | super(SyncMultiGPUReplicatedBuilder, self).__init__(towers) |
| 209 | self._average = average |
| 210 | assert mode in ['nccl', 'cpu', 'hierarchical', 'gpu', 'collective'], mode |
| 211 | self._mode = mode |
| 212 | |
| 213 | if self._mode == 'hierarchical' and len(towers) != 8: |
| 214 | raise ValueError("mode='hierarchical' require 8 GPUs.") |
| 215 | |
| 216 | def call_for_each_tower(self, tower_fn): |
| 217 | """ |
| 218 | Call the function `tower_fn` under :class:`TowerContext` for each tower. |
| 219 | |
| 220 | Returns: |
| 221 | a list, contains the return values of `tower_fn` on each tower. |
| 222 | """ |
| 223 | # if tower_fn returns [(grad, var), ...], this returns #GPU x #VAR x 2 |
| 224 | return DataParallelBuilder.build_on_towers( |
| 225 | self.towers, |
| 226 | tower_fn, |
| 227 | # use no variable scope for the first tower |
| 228 | use_vs=[False] + [True] * (len(self.towers) - 1)) |
| 229 | |
| 230 | def build(self, grad_list, get_opt_fn): |
| 231 | """ |
| 232 | Reduce the gradients, apply them with the optimizer, |
| 233 | and set self.grads to #GPU number of lists of (g, v), containing the all-reduced gradients on each device. |
| 234 | |
| 235 | Args: |
| 236 | grad_list ([[(grad, var), ...], ...]): #GPU lists to be reduced. Each is the gradients computed on each GPU. |
| 237 | get_opt_fn (-> tf.train.Optimizer): callable which returns an optimizer |
| 238 | |
| 239 | Returns: |
| 240 | (tf.Operation, tf.Operation) |
| 241 | |
| 242 | 1. the training op. |
| 243 | |
| 244 | 2. the op which sync variables from GPU 0 to other GPUs. |
| 245 | It has to be run before the training has started. |
| 246 | And you can optionally run it later to sync non-trainable variables. |
| 247 | """ |
| 248 | assert len(grad_list) == len(self.towers) |
| 249 | raw_devices = ['/gpu:{}'.format(k) for k in self.towers] |
| 250 | |
| 251 | DataParallelBuilder._check_grad_list(grad_list) |
| 252 | |
| 253 | dtypes = {x[0].dtype.base_dtype for x in grad_list[0]} |