:attr:`backward` performs the following conceptual steps: 1. fp32_loss = loss.float() (see first Note below) 2. scaled_loss = fp32_loss*loss_scale 3. scaled_loss.backward(), which accumulates scaled gradients into the ``.grad`` attributes of the model's leaves (whi
(self, loss, update_master_grads=True, retain_graph=False)
| 504 | return retval |
| 505 | |
| 506 | def backward(self, loss, update_master_grads=True, retain_graph=False): |
| 507 | """ |
| 508 | :attr:`backward` performs the following conceptual steps: |
| 509 | |
| 510 | 1. fp32_loss = loss.float() (see first Note below) |
| 511 | 2. scaled_loss = fp32_loss*loss_scale |
| 512 | 3. scaled_loss.backward(), which accumulates scaled gradients into the ``.grad`` attributes of the model's leaves (which may be fp16, fp32, or a mixture, depending how your model was defined). |
| 513 | 4. fp16 grads are then copied to the master params' ``.grad`` attributes (see second Note), which are guaranteed to be fp32. |
| 514 | 5. Finally, master grads are divided by loss_scale. |
| 515 | |
| 516 | In this way, after :attr:`backward`, the master params have fresh gradients, |
| 517 | and :attr:`step` may be called. |
| 518 | |
| 519 | .. note:: |
| 520 | :attr:`backward` internally converts the loss to fp32 before applying the loss scale. |
| 521 | This provides some additional safety against overflow if the user has supplied an |
| 522 | fp16 loss value. |
| 523 | However, for maximum overflow safety, the user should |
| 524 | compute the loss criterion (MSE, cross entropy, etc) in fp32 before supplying it to |
| 525 | :attr:`backward`. |
| 526 | |
| 527 | .. warning:: |
| 528 | The gradients found in a model's leaves after the call to |
| 529 | :attr:`backward` should not be regarded as valid in general, |
| 530 | because it's possible |
| 531 | they have been scaled (and in the case of dynamic loss scaling, |
| 532 | the scale factor may change over time). |
| 533 | If the user wants to inspect gradients after a call to :attr:`backward`, |
| 534 | only the master gradients should be regarded as valid. These can be retrieved via |
| 535 | :attr:`inspect_master_grad_data()`. |
| 536 | |
| 537 | Args: |
| 538 | loss: The loss output by the user's model. loss may be either float or half (but see first Note above). |
| 539 | update_master_grads (bool, optional, default=True): Option to copy fp16 grads to fp32 grads on this call. By setting this to False, the user can delay the copy, which is useful to eliminate redundant fp16->fp32 grad copies if :attr:`backward` is being called on multiple losses in one iteration. If set to False, the user becomes responsible for calling :attr:`update_master_grads` before calling :attr:`step`. |
| 540 | retain_graph (bool, optional, default=False): Forwards the usual ``retain_graph=True`` option to the internal call to ``loss.backward``. If ``retain_graph`` is being used to accumulate gradient values from multiple backward passes before calling ``optimizer.step``, passing ``update_master_grads=False`` is also recommended (see Example below). |
| 541 | |
| 542 | Example:: |
| 543 | |
| 544 | # Ordinary operation: |
| 545 | optimizer.backward(loss) |
| 546 | |
| 547 | # Naive operation with multiple losses (technically valid, but less efficient): |
| 548 | # fp32 grads will be correct after the second call, but |
| 549 | # the first call incurs an unnecessary fp16->fp32 grad copy. |
| 550 | optimizer.backward(loss1) |
| 551 | optimizer.backward(loss2) |
| 552 | |
| 553 | # More efficient way to handle multiple losses: |
| 554 | # The fp16->fp32 grad copy is delayed until fp16 grads from all |
| 555 | # losses have been accumulated. |
| 556 | optimizer.backward(loss1, update_master_grads=False) |
| 557 | optimizer.backward(loss2, update_master_grads=False) |
| 558 | optimizer.update_master_grads() |
| 559 | """ |
| 560 | # To consider: try multiple backward passes using retain_grad=True to find |
| 561 | # a loss scale that works. After you find a loss scale that works, do a final dummy |
| 562 | # backward pass with retain_graph=False to tear down the graph. Doing this would avoid |
| 563 | # discarding the iteration, but probably wouldn't improve overall efficiency. |
no test coverage detected