main
py 98 lines 3.22 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Common Qwen4Exp PLE helpers."""
4
5 from dataclasses import dataclass
6
7 import torch
8
9 from vllm.model_executor.layers.vocab_parallel_embedding import (
10 VocabParallelEmbedding,
11 )
12
13
14 @dataclass(frozen=True)
15 class PLEShardOverlap:
16 """Source and destination slices for one checkpoint embedding shard."""
17
18 source_start: int
19 destination_start: int
20 row_count: int
21
22
23 def compute_ple_shard_overlap(
24 *,
25 checkpoint_start: int,
26 checkpoint_rows: int,
27 tp_start: int,
28 tp_end: int,
29 ) -> PLEShardOverlap | None:
30 """Compute the overlap of a checkpoint shard and one TP vocabulary range."""
31 if checkpoint_start < 0 or checkpoint_rows < 0:
32 raise ValueError("checkpoint shard bounds must be non-negative")
33 if tp_start < 0 or tp_end < tp_start:
34 raise ValueError("invalid TP vocabulary range")
35 checkpoint_end = checkpoint_start + checkpoint_rows
36 overlap_start = max(checkpoint_start, tp_start)
37 overlap_end = min(checkpoint_end, tp_end)
38 if overlap_start >= overlap_end:
39 return None
40 return PLEShardOverlap(
41 source_start=overlap_start - checkpoint_start,
42 destination_start=overlap_start - tp_start,
43 row_count=overlap_end - overlap_start,
44 )
45
46
47 def copy_ple_embedding_shard_(
48 destination: torch.Tensor,
49 loaded_weight: torch.Tensor,
50 *,
51 checkpoint_start: int,
52 tp_start: int,
53 tp_end: int,
54 ) -> int:
55 """Copy the overlapping rows of a PLE checkpoint shard into a TP table."""
56 if destination.ndim == 0 or loaded_weight.ndim != destination.ndim:
57 raise ValueError("destination and loaded weight must have matching ranks")
58 if destination.shape[1:] != loaded_weight.shape[1:]:
59 raise ValueError(
60 "embedding shard dimensions do not match: "
61 f"{tuple(destination.shape[1:])} != {tuple(loaded_weight.shape[1:])}"
62 )
63 if destination.shape[0] < tp_end - tp_start:
64 raise ValueError("destination does not cover the requested TP range")
65 overlap = compute_ple_shard_overlap(
66 checkpoint_start=checkpoint_start,
67 checkpoint_rows=loaded_weight.shape[0],
68 tp_start=tp_start,
69 tp_end=tp_end,
70 )
71 if overlap is None:
72 return 0
73 source = loaded_weight.narrow(0, overlap.source_start, overlap.row_count)
74 target = destination.narrow(0, overlap.destination_start, overlap.row_count)
75 with torch.no_grad():
76 target.copy_(source.to(device=target.device, dtype=target.dtype))
77 return overlap.row_count
78
79
80 class PLEVocabParallelEmbedding(VocabParallelEmbedding):
81 """Vocab-parallel embedding that accepts checkpoint row shards."""
82
83 def weight_loader(
84 self,
85 param: torch.Tensor,
86 loaded_weight: torch.Tensor,
87 checkpoint_start: int | None = None,
88 ) -> None:
89 if checkpoint_start is None:
90 super().weight_loader(param, loaded_weight)
91 return
92 copy_ple_embedding_shard_(
93 param,
94 loaded_weight,
95 checkpoint_start=checkpoint_start,
96 tp_start=self.shard_indices.org_vocab_start_index,
97 tp_end=self.shard_indices.org_vocab_end_index,
98 )