[cuda-graph] Size breakable-graph shared buffer from warmup output; slice by produced row count (#30834)
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -110,10 +110,11 @@ class BreakableCudaGraphBackend(DedupedCudaGraphMixin, BaseCudaGraphBackend):
|
|||||||
dummies: Optional[Any] = None,
|
dummies: Optional[Any] = None,
|
||||||
post_warmup_hook: Optional[Callable[[], None]] = None,
|
post_warmup_hook: Optional[Callable[[], None]] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
|
warmup_out = None
|
||||||
for _ in range(2):
|
for _ in range(2):
|
||||||
self._device_module.synchronize()
|
self._device_module.synchronize()
|
||||||
self._tp_group.barrier()
|
self._tp_group.barrier()
|
||||||
forward_fn()
|
warmup_out = forward_fn()
|
||||||
if post_warmup_hook is not None:
|
if post_warmup_hook is not None:
|
||||||
post_warmup_hook()
|
post_warmup_hook()
|
||||||
|
|
||||||
@@ -122,24 +123,55 @@ class BreakableCudaGraphBackend(DedupedCudaGraphMixin, BaseCudaGraphBackend):
|
|||||||
eager_on_graph(True)(forward_fn) if self._debug_eager else forward_fn
|
eager_on_graph(True)(forward_fn) if self._debug_eager else forward_fn
|
||||||
)
|
)
|
||||||
size = shape_key.size
|
size = shape_key.size
|
||||||
|
if self._shared_output_buffer is None:
|
||||||
|
self._shared_output_buffer = self._alloc_full_buffer(warmup_out, size)
|
||||||
with BreakableCUDAGraphCapture(
|
with BreakableCUDAGraphCapture(
|
||||||
cuda_graph=graph,
|
cuda_graph=graph,
|
||||||
pool=self._pool,
|
pool=self._pool,
|
||||||
stream=self._capture_stream,
|
stream=self._capture_stream,
|
||||||
):
|
):
|
||||||
out = captured_fn()
|
out = captured_fn()
|
||||||
if self._shared_output_buffer is not None:
|
out_rows = self._output_rows(out, size)
|
||||||
self._copy_output_to_buffer(out, self._shared_output_buffer, size)
|
self._copy_output_to_buffer(out, self._shared_output_buffer, out_rows)
|
||||||
|
|
||||||
if self._shared_output_buffer is None:
|
|
||||||
self._shared_output_buffer = out
|
|
||||||
stored = self._slice_output(out, size)
|
|
||||||
else:
|
|
||||||
stored = self._slice_output(self._shared_output_buffer, size)
|
|
||||||
|
|
||||||
|
stored = self._slice_output(self._shared_output_buffer, out_rows)
|
||||||
self._graphs[shape_key] = graph
|
self._graphs[shape_key] = graph
|
||||||
self._outputs[shape_key] = stored
|
self._outputs[shape_key] = stored
|
||||||
|
|
||||||
|
def _output_rows(self, output: Any, cap: int) -> int:
|
||||||
|
"""Leading-dim row count actually produced by the body, clamped to ``cap``.
|
||||||
|
|
||||||
|
A body that shards or prunes its output along dim 0 returns fewer than
|
||||||
|
``cap`` rows; everything else returns exactly ``cap``.
|
||||||
|
"""
|
||||||
|
if torch.is_tensor(output):
|
||||||
|
return min(cap, output.shape[0])
|
||||||
|
if isinstance(output, PPProxyTensors):
|
||||||
|
rows = [t.shape[0] for t in output.tensors.values()]
|
||||||
|
return min([cap, *rows])
|
||||||
|
if isinstance(output, (list, tuple)) and output:
|
||||||
|
return min(self._output_rows(o, cap) for o in output if o is not None)
|
||||||
|
return cap
|
||||||
|
|
||||||
|
def _alloc_full_buffer(self, output: Any, size: int) -> Any:
|
||||||
|
"""A same-structure buffer as ``output`` but with ``size`` leading rows."""
|
||||||
|
if output is None:
|
||||||
|
return None
|
||||||
|
if torch.is_tensor(output):
|
||||||
|
return output.new_empty((size, *output.shape[1:]))
|
||||||
|
if isinstance(output, PPProxyTensors):
|
||||||
|
return PPProxyTensors(
|
||||||
|
{
|
||||||
|
key: t.new_empty((size, *t.shape[1:]))
|
||||||
|
for key, t in output.tensors.items()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if isinstance(output, tuple):
|
||||||
|
return tuple(self._alloc_full_buffer(o, size) for o in output)
|
||||||
|
if isinstance(output, list):
|
||||||
|
return [self._alloc_full_buffer(o, size) for o in output]
|
||||||
|
raise TypeError(f"Unsupported BCG output type: {type(output)}")
|
||||||
|
|
||||||
def _slice_output(self, output: Any, num_tokens: int) -> Any:
|
def _slice_output(self, output: Any, num_tokens: int) -> Any:
|
||||||
if output is None:
|
if output is None:
|
||||||
return None
|
return None
|
||||||
|
|||||||
Reference in New Issue
Block a user