roce_gather.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445
  1. """Route small TP all-gathers through the RoCEnante one-shot kernel (DSV41_ROCE_GATHER=<max bytes per rank>).
  2. The SG17 overlay builds the runtime with max_gather_bytes=0, so every all-gather (draft logits /
  3. markov gathers, a few per step) still goes to NCCL. The runtime's slots are max(max_size, gather)
  4. wide, so any shard up to max_size fits without re-sizing; the gather launcher and the padded
  5. scratch are prepared here, before CUDA graph capture. Byte copy: outputs are bit-identical.
  6. """
  7. import logging
  8. import os
  9. logger = logging.getLogger(__name__)
  10. def install(module):
  11. cls = module.PyNcclCommunicator
  12. limit = int(os.environ.get('DSV41_ROCE_GATHER', '0') or 0)
  13. orig_init, orig_gather = cls.__init__, cls.all_gather
  14. def __init__(self, *args, **kwargs):
  15. orig_init(self, *args, **kwargs)
  16. roce = getattr(self, 'roce', None)
  17. if roce is None or limit <= 0:
  18. return
  19. roce.max_gather_bytes = min(limit, roce._slot_bytes)
  20. roce.prepare((), padded_gather=True)
  21. self._roce_gather_logged = False
  22. logger.info('DSV41_ROCE_GATHER ready: max %d bytes per rank', roce.max_gather_bytes)
  23. def all_gather(self, output_tensor, input_tensor, sizes=None):
  24. roce = getattr(self, 'roce', None)
  25. if (roce is not None and not self.disabled and sizes is None and roce.max_gather_bytes > 0
  26. and output_tensor.is_contiguous()
  27. and output_tensor.numel() == input_tensor.numel() * self.world_size
  28. and roce.should_all_gather(input_tensor, 0)):
  29. out = output_tensor.view(self.world_size * input_tensor.shape[0], *input_tensor.shape[1:]) \
  30. if input_tensor.dim() > 0 else output_tensor
  31. roce.all_gather(input_tensor, dim=0, out=out, stream=self._resolve_stream())
  32. if not self._roce_gather_logged:
  33. logger.info('DSV41_ROCE_GATHER route rank=%d dtype=%s bytes=%d', self.rank,
  34. input_tensor.dtype, input_tensor.numel() * input_tensor.element_size())
  35. self._roce_gather_logged = True
  36. return
  37. return orig_gather(self, output_tensor, input_tensor, sizes)
  38. cls.__init__, cls.all_gather = __init__, all_gather