| 72 | |
| 73 | |
| 74 | class LossAwareSampler(ScheduleSampler): |
| 75 | |
| 76 | def update_with_local_losses(self, local_ts, local_losses): |
| 77 | """ |
| 78 | Update the reweighting using losses from a model. |
| 79 | Call this method from each rank with a batch of timesteps and the |
| 80 | corresponding losses for each of those timesteps. |
| 81 | This method will perform synchronization to make sure all of the ranks |
| 82 | maintain the exact same reweighting. |
| 83 | :param local_ts: an integer Tensor of timesteps. |
| 84 | :param local_losses: a 1D Tensor of losses. |
| 85 | """ |
| 86 | batch_sizes = [ |
| 87 | th.tensor([0], dtype=th.int32, device=local_ts.device) |
| 88 | for _ in range(dist.get_world_size()) |
| 89 | ] |
| 90 | dist.all_gather( |
| 91 | batch_sizes, |
| 92 | th.tensor([len(local_ts)], dtype=th.int32, device=local_ts.device), |
| 93 | ) |
| 94 | |
| 95 | # Pad all_gather batches to be the maximum batch size. |
| 96 | batch_sizes = [x.item() for x in batch_sizes] |
| 97 | max_bs = max(batch_sizes) |
| 98 | |
| 99 | timestep_batches = [ |
| 100 | th.zeros(max_bs).to(local_ts) for bs in batch_sizes |
| 101 | ] |
| 102 | loss_batches = [ |
| 103 | th.zeros(max_bs).to(local_losses) for bs in batch_sizes |
| 104 | ] |
| 105 | dist.all_gather(timestep_batches, local_ts) |
| 106 | dist.all_gather(loss_batches, local_losses) |
| 107 | timesteps = [ |
| 108 | x.item() for y, bs in zip(timestep_batches, batch_sizes) |
| 109 | for x in y[:bs] |
| 110 | ] |
| 111 | losses = [ |
| 112 | x.item() for y, bs in zip(loss_batches, batch_sizes) |
| 113 | for x in y[:bs] |
| 114 | ] |
| 115 | self.update_with_all_losses(timesteps, losses) |
| 116 | |
| 117 | @abstractmethod |
| 118 | def update_with_all_losses(self, ts, losses): |
| 119 | """ |
| 120 | Update the reweighting using losses from a model. |
| 121 | Sub-classes should override this method to update the reweighting |
| 122 | using losses from the model. |
| 123 | This method directly updates the reweighting without synchronizing |
| 124 | between workers. It is called by update_with_local_losses from all |
| 125 | ranks with identical arguments. Thus, it should have deterministic |
| 126 | behavior to maintain state across workers. |
| 127 | :param ts: a list of int timesteps. |
| 128 | :param losses: a list of float losses, one per timestep. |
| 129 | """ |
| 130 | |
| 131 |
nothing calls this directly
no outgoing calls
no test coverage detected