|
35 | 35 | import torch |
36 | 36 | import torch.nn as nn |
37 | 37 |
|
38 | | -from xllm.python import kernels |
| 38 | +from xllm.python import distributed, kernels |
39 | 39 | from xllm.python.attention.backend import AttentionBackend, AttentionMetadata |
40 | 40 | from xllm.python.attention.expanded_decode_metadata import ( |
41 | 41 | ExpandedDecodeMetadata, |
@@ -138,14 +138,20 @@ def can_execute( |
138 | 138 | if input_ids.dim() != 1: |
139 | 139 | return False |
140 | 140 | batch_size = input_ids.numel() |
141 | | - bucket_size = _decode_bucket(batch_size) |
142 | 141 | is_expanded_spec_verify = resolve_expanded_decode_metadata(metadata) is not None |
143 | | - return ( |
| 142 | + if not ( |
144 | 143 | ((not metadata.is_prefill and not metadata.is_chunked_prefill) or is_expanded_spec_verify) |
145 | 144 | and self._has_compatible_decode_metadata(input_ids, metadata) |
146 | 145 | and (input_embedding is None or input_embedding.shape[0] == batch_size) |
147 | | - and bucket_size <= self.max_batch |
148 | | - ) |
| 146 | + ): |
| 147 | + return False |
| 148 | + if self.dp_size > 1: |
| 149 | + dp_token_counts = getattr(metadata, "dp_token_counts", None) |
| 150 | + if dp_token_counts is None or len(dp_token_counts) != self.dp_size: |
| 151 | + return False |
| 152 | + global_batch = max(max(int(c) for c in dp_token_counts), batch_size) |
| 153 | + return _decode_bucket(global_batch) <= self.max_batch |
| 154 | + return _decode_bucket(batch_size) <= self.max_batch |
149 | 155 |
|
150 | 156 | def _decode_metadata( |
151 | 157 | self, metadata: AttentionMetadata |
@@ -385,7 +391,14 @@ def execute( |
385 | 391 | input_embedding: torch.Tensor | None = None, |
386 | 392 | ) -> torch.Tensor: |
387 | 393 | batch_size = input_ids.shape[0] |
388 | | - padded_batch_size = _decode_bucket(batch_size) |
| 394 | + |
| 395 | + if self.dp_size > 1: |
| 396 | + dp_token_counts = tuple(int(c) for c in metadata.dp_token_counts) |
| 397 | + global_batch = max(max(dp_token_counts, default=0), batch_size) |
| 398 | + padded_batch_size = _decode_bucket(global_batch) |
| 399 | + else: |
| 400 | + padded_batch_size = _decode_bucket(batch_size) |
| 401 | + |
389 | 402 | if padded_batch_size > self.max_batch: |
390 | 403 | raise ValueError("decode batch exceeds ACL graph capacity") |
391 | 404 |
|
@@ -418,6 +431,9 @@ def execute( |
418 | 431 | self.attention_backend.prepare(entry.static_metadata, graph_mode=True) |
419 | 432 |
|
420 | 433 | if first_capture: |
| 434 | + self._stream.wait_stream(torch.npu.current_stream()) |
| 435 | + if self.dp_size > 1: |
| 436 | + distributed.barrier(self.device, "dp") |
421 | 437 | self._capture(entry) |
422 | 438 |
|
423 | 439 | self._stream.wait_stream(torch.npu.current_stream()) |
@@ -524,6 +540,7 @@ def _allocate_entry( |
524 | 540 | paged_kv_last_page_len_host=torch.ones(padded_batch_size, dtype=torch.int32, device="cpu"), |
525 | 541 | kv_seq_lens_host_values=[1] * padded_batch_size, |
526 | 542 | block_table=static_block_table, |
| 543 | + dp_token_counts=tuple([padded_batch_size] * self.dp_size) if self.dp_size > 1 else (), |
527 | 544 | ) |
528 | 545 | is_expanded = resolve_expanded_decode_metadata(metadata) is not None |
529 | 546 | entry.kv_seq_lens_delta = torch.empty(padded_batch_size, dtype=torch.int32, device=device) |
@@ -663,7 +680,7 @@ def _capture(self, entry: _DecodeGraphEntry) -> None: |
663 | 680 | self.layer_caches, |
664 | 681 | execution_state=entry.execution_state, |
665 | 682 | ) |
666 | | - with forward_context(context): |
| 683 | + with forward_context(context), torch.npu.stream(self._stream): |
667 | 684 | for _ in range(_CAPTURE_WARMUP_STEPS): |
668 | 685 | self._forward_static(entry) |
669 | 686 | torch.npu.synchronize() |
|
0 commit comments