(self, buffer_id)
| 716 | return batch |
| 717 | |
| 718 | def _exec_forward_pass(self, buffer_id): |
| 719 | self.tput_timer.start() |
| 720 | |
| 721 | if isinstance(self.pipe_buffers['inputs'][buffer_id], tuple): |
| 722 | inputs = tuple(t.clone() for t in self.pipe_buffers['inputs'][buffer_id]) |
| 723 | else: |
| 724 | inputs = self.pipe_buffers['inputs'][buffer_id].clone() |
| 725 | |
| 726 | # collect the partitioned input from the previous stage |
| 727 | if self.is_pipe_partitioned and not self.is_first_stage(): |
| 728 | if self.pipe_partition_input_meta_cache is None: |
| 729 | self.pipe_partition_input_meta_cache = inputs[0].to('cpu') |
| 730 | part_input = PartitionedTensor.from_meta(meta=self.pipe_partition_input_meta_cache, |
| 731 | local_part=inputs[1], |
| 732 | group=self.grid.get_slice_parallel_group()) |
| 733 | |
| 734 | inputs = (part_input.full(), *inputs[2:]) |
| 735 | inputs[0].requires_grad = True |
| 736 | # skip mask |
| 737 | #inputs[1].requires_grad = True |
| 738 | part_input = None |
| 739 | inputs = inputs[0] if len(inputs) == 1 else inputs |
| 740 | self.pipe_buffers['inputs'][buffer_id] = inputs |
| 741 | |
| 742 | # inputs has no gradient because it is from a cloned tensor |
| 743 | outputs = super().forward(inputs) |
| 744 | |
| 745 | # Reset activation checkpointing buffers. |
| 746 | # Need to call this between evaluation iterations |
| 747 | if not self.module.training: |
| 748 | ds_checkpointing.reset() |
| 749 | |
| 750 | # Partition the outputs if we are not the last stage |
| 751 | if self.is_pipe_partitioned and not self.is_last_stage(): |
| 752 | if isinstance(outputs, tuple): |
| 753 | first_output = outputs[0] |
| 754 | # TODO: Improve pipe partitioning to pass multiple tensors that require grads |
| 755 | assert all([torch.is_tensor(elt) and elt.requires_grad is False for elt in outputs[1:]]) |
| 756 | outputs_tail = outputs[1:] |
| 757 | elif torch.is_tensor(outputs): |
| 758 | first_output = outputs |
| 759 | outputs_tail = [] |
| 760 | else: |
| 761 | raise ValueError("expecting a tensor or a tuple of tensors") |
| 762 | part = PartitionedTensor(tensor=first_output, group=self.grid.get_slice_parallel_group()) |
| 763 | # Clear the large output data, but save the computation graph |
| 764 | first_output.data = torch.zeros(1, device=first_output.data.device) |
| 765 | self.pipe_buffers['output_tensors'][buffer_id] = first_output |
| 766 | # Inject the partitioned tensor into the output before sending |
| 767 | outputs = (part.to_meta(), part.data(), *outputs_tail) |
| 768 | part = None |
| 769 | |
| 770 | self.pipe_buffers['outputs'][buffer_id] = outputs |
| 771 | |
| 772 | # Optionally compute loss on the last device |
| 773 | if self.is_last_stage(): |
| 774 | if self._compute_loss and self.module.loss_fn is not None: |
| 775 | labels = self.pipe_buffers['labels'][buffer_id] |
nothing calls this directly
no test coverage detected