vocab_parallel_embedding.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650
  1. # SPDX-License-Identifier: Apache-2.0
  2. # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
  3. from collections.abc import Sequence
  4. from dataclasses import dataclass
  5. import torch
  6. import torch.nn.functional as F
  7. from torch.nn.parameter import Parameter
  8. import vllm.envs as envs
  9. from vllm import _custom_ops as ops
  10. from vllm.distributed import (
  11. GroupCoordinator,
  12. divide,
  13. get_tensor_model_parallel_rank,
  14. get_tensor_model_parallel_world_size,
  15. tensor_model_parallel_all_reduce,
  16. )
  17. from vllm.model_executor.custom_op import PluggableLayer
  18. from vllm.model_executor.determinism.batch_invariant import (
  19. linear_batch_invariant,
  20. )
  21. from vllm.model_executor.layers.quantization.base_config import (
  22. QuantizationConfig,
  23. QuantizeMethodBase,
  24. method_has_implemented_embedding,
  25. resolve_quant_method,
  26. )
  27. from vllm.model_executor.layers.utils import dispatch_unquantized_gemm
  28. from vllm.model_executor.parameter import BasevLLMParameter
  29. from vllm.model_executor.utils import set_weight_attrs
  30. from vllm.platforms import current_platform
  31. DEFAULT_VOCAB_PADDING_SIZE = 64
  32. class UnquantizedEmbeddingMethod(QuantizeMethodBase):
  33. """Unquantized method for embeddings."""
  34. supports_pre_processed_weights = True
  35. def create_weights(
  36. self,
  37. layer: torch.nn.Module,
  38. input_size_per_partition: int,
  39. output_partition_sizes: list[int],
  40. input_size: int,
  41. output_size: int,
  42. params_dtype: torch.dtype,
  43. **extra_weight_attrs,
  44. ):
  45. """Create weights for embedding layer."""
  46. weight = Parameter(
  47. torch.empty(
  48. sum(output_partition_sizes),
  49. input_size_per_partition,
  50. dtype=params_dtype,
  51. ),
  52. requires_grad=False,
  53. )
  54. set_weight_attrs(weight, {"input_dim": 1, "output_dim": 0})
  55. layer.register_parameter("weight", weight)
  56. set_weight_attrs(weight, extra_weight_attrs)
  57. def process_weights_after_loading(self, layer: torch.nn.Module) -> None:
  58. if current_platform.is_cpu():
  59. from vllm.model_executor.layers.utils import dispatch_cpu_unquantized_gemm
  60. dispatch_cpu_unquantized_gemm(layer, remove_weight=False)
  61. def apply(
  62. self,
  63. layer: torch.nn.Module,
  64. x: torch.Tensor,
  65. bias: torch.Tensor | None = None,
  66. ) -> torch.Tensor:
  67. if envs.VLLM_BATCH_INVARIANT and (
  68. current_platform.is_cuda_alike() or current_platform.is_xpu()
  69. ):
  70. return linear_batch_invariant(x, layer.weight, bias)
  71. return dispatch_unquantized_gemm()(layer, x, layer.weight, bias)
  72. def embedding(self, layer: torch.nn.Module, input_: torch.Tensor) -> torch.Tensor:
  73. return F.embedding(input_, layer.weight)
  74. def tie_weights(
  75. self, layer: torch.nn.Module, embed_tokens: "VocabParallelEmbedding"
  76. ):
  77. layer.weight = embed_tokens.weight
  78. return layer
  79. def pad_vocab_size(vocab_size: int, pad_to: int = DEFAULT_VOCAB_PADDING_SIZE) -> int:
  80. """Pad the vocab size to the given value."""
  81. return ((vocab_size + pad_to - 1) // pad_to) * pad_to
  82. def vocab_range_from_per_partition_vocab_size(
  83. per_partition_vocab_size: int, rank: int, offset: int = 0
  84. ) -> Sequence[int]:
  85. index_f = rank * per_partition_vocab_size
  86. index_l = index_f + per_partition_vocab_size
  87. return index_f + offset, index_l + offset
  88. def vocab_range_from_global_vocab_size(
  89. global_vocab_size: int, rank: int, world_size: int, offset: int = 0
  90. ) -> Sequence[int]:
  91. per_partition_vocab_size = divide(global_vocab_size, world_size)
  92. return vocab_range_from_per_partition_vocab_size(
  93. per_partition_vocab_size, rank, offset=offset
  94. )
  95. @dataclass
  96. class VocabParallelEmbeddingShardIndices:
  97. """Indices for a shard of a vocab parallel embedding."""
  98. padded_org_vocab_start_index: int
  99. padded_org_vocab_end_index: int
  100. padded_added_vocab_start_index: int
  101. padded_added_vocab_end_index: int
  102. org_vocab_start_index: int
  103. org_vocab_end_index: int
  104. added_vocab_start_index: int
  105. added_vocab_end_index: int
  106. @property
  107. def num_org_elements(self) -> int:
  108. return self.org_vocab_end_index - self.org_vocab_start_index
  109. @property
  110. def num_added_elements(self) -> int:
  111. return self.added_vocab_end_index - self.added_vocab_start_index
  112. @property
  113. def num_org_elements_padded(self) -> int:
  114. return self.padded_org_vocab_end_index - self.padded_org_vocab_start_index
  115. @property
  116. def num_added_elements_padded(self) -> int:
  117. return self.padded_added_vocab_end_index - self.padded_added_vocab_start_index
  118. @property
  119. def num_org_vocab_padding(self) -> int:
  120. return self.num_org_elements_padded - self.num_org_elements
  121. @property
  122. def num_added_vocab_padding(self) -> int:
  123. return self.num_added_elements_padded - self.num_added_elements
  124. @property
  125. def num_elements_padded(self) -> int:
  126. return self.num_org_elements_padded + self.num_added_elements_padded
  127. def __post_init__(self):
  128. # sanity checks
  129. assert self.padded_org_vocab_start_index <= self.padded_org_vocab_end_index
  130. assert self.padded_added_vocab_start_index <= self.padded_added_vocab_end_index
  131. assert self.org_vocab_start_index <= self.org_vocab_end_index
  132. assert self.added_vocab_start_index <= self.added_vocab_end_index
  133. assert self.org_vocab_start_index <= self.padded_org_vocab_start_index
  134. assert self.added_vocab_start_index <= self.padded_added_vocab_start_index
  135. assert self.org_vocab_end_index <= self.padded_org_vocab_end_index
  136. assert self.added_vocab_end_index <= self.padded_added_vocab_end_index
  137. assert self.num_org_elements <= self.num_org_elements_padded
  138. assert self.num_added_elements <= self.num_added_elements_padded
  139. @torch.compile(dynamic=True, backend=current_platform.simple_compile_backend)
  140. def get_masked_input_and_mask(
  141. input_: torch.Tensor,
  142. org_vocab_start_index: int,
  143. org_vocab_end_index: int,
  144. num_org_vocab_padding: int,
  145. added_vocab_start_index: int,
  146. added_vocab_end_index: int,
  147. ) -> tuple[torch.Tensor, torch.Tensor]:
  148. # torch.compile will fuse all of the pointwise ops below
  149. # into a single kernel, making it very fast
  150. org_vocab_mask = (input_ >= org_vocab_start_index) & (input_ < org_vocab_end_index)
  151. added_vocab_mask = (input_ >= added_vocab_start_index) & (
  152. input_ < added_vocab_end_index
  153. )
  154. added_offset = (
  155. added_vocab_start_index
  156. - (org_vocab_end_index - org_vocab_start_index)
  157. - num_org_vocab_padding
  158. )
  159. valid_offset = (org_vocab_start_index * org_vocab_mask) + (
  160. added_offset * added_vocab_mask
  161. )
  162. vocab_mask = org_vocab_mask | added_vocab_mask
  163. input_ = vocab_mask * (input_ - valid_offset)
  164. return input_, ~vocab_mask
  165. # --8<-- [start:vocab_parallel_embedding]
  166. @PluggableLayer.register("vocab_parallel_embedding")
  167. class VocabParallelEmbedding(PluggableLayer):
  168. """Embedding parallelized in the vocabulary dimension.
  169. Adapted from torch.nn.Embedding, note that we pad the vocabulary size to
  170. make sure it is divisible by the number of model parallel GPUs.
  171. In order to support various loading methods, we ensure that LoRA-added
  172. embeddings are always at the end of TP-sharded tensors. In other words,
  173. we shard base embeddings and LoRA embeddings separately (both padded),
  174. and place them in the same tensor.
  175. In this example, we will have the original vocab size = 1010,
  176. added vocab size = 16 and padding to 64. Therefore, the total
  177. vocab size with padding will be 1088 (because we first pad 1010 to
  178. 1024, add 16, and then pad to 1088).
  179. Therefore, the tensor format looks like the following:
  180. TP1, rank 0 (no sharding):
  181. |< --------BASE-------- >|< -BASE PADDING-- >|< -----LORA------ >|< -LORA PADDING-- >|
  182. corresponding token_id: | 0 | 1 | ... | 1009 | -1 | ... | -1 | 1010 | ... | 1025 | -1 | ... | -1 |
  183. index: | 0 | 1 | ... | 1009 | 1010 | ... | 1023 | 1024 | ... | 1039 | 1040 | ... | 1087 |
  184. TP2, rank 0:
  185. |< --------------------BASE--------------------- >|< -----LORA------ >|< -LORA PADDING- >|
  186. corresponding token_id: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 1010 | ... | 1025 | -1 | ... | -1 |
  187. index: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 512 | ... | 527 | 528 | ... | 543 |
  188. TP2, rank 1:
  189. |< -----------BASE----------- >|< -BASE PADDING- >|< -----------LORA PADDING----------- >|
  190. corresponding token_id: | 512 | 513 | 514 | ... | 1009 | -1 | ... | -1 | -1 | ... | -1 | -1 | ... | -1 |
  191. index: | 0 | 1 | 2 | ... | 497 | 498 | ... | 511 | 512 | ... | 527 | 528 | ... | 543 |
  192. Args:
  193. num_embeddings: vocabulary size.
  194. embedding_dim: size of hidden state.
  195. params_dtype: type of the parameters.
  196. org_num_embeddings: original vocabulary size (without LoRA).
  197. padding_size: padding size for the vocabulary.
  198. quant_config: quant config for the layer
  199. prefix: full name of the layer in the state dict
  200. disable_tp: If true, tensor parallelism will be disabled for this layer.
  201. quant_method: Preselected quantization method for model-specific layers.
  202. parallel_group: Process group used to shard and reduce the embedding.
  203. """ # noqa: E501
  204. # --8<-- [end:vocab_parallel_embedding]
  205. def __init__(
  206. self,
  207. num_embeddings: int,
  208. embedding_dim: int,
  209. params_dtype: torch.dtype | None = None,
  210. org_num_embeddings: int | None = None,
  211. padding_size: int = DEFAULT_VOCAB_PADDING_SIZE,
  212. quant_config: QuantizationConfig | None = None,
  213. prefix: str = "",
  214. *,
  215. disable_tp: bool = False,
  216. quant_method: QuantizeMethodBase | None = None,
  217. parallel_group: GroupCoordinator | None = None,
  218. ):
  219. super().__init__()
  220. # Keep the input dimensions.
  221. self.disable_tp = disable_tp
  222. self.parallel_group = parallel_group
  223. if disable_tp:
  224. tp_rank, self.tp_size = 0, 1
  225. elif parallel_group is not None:
  226. tp_rank = parallel_group.rank_in_group
  227. self.tp_size = parallel_group.world_size
  228. else:
  229. tp_rank = get_tensor_model_parallel_rank()
  230. self.tp_size = get_tensor_model_parallel_world_size()
  231. self.tp_rank = tp_rank
  232. self.num_embeddings = num_embeddings
  233. self.padding_size = padding_size
  234. self.org_vocab_size = org_num_embeddings or num_embeddings
  235. self.num_added_embeddings = num_embeddings - self.org_vocab_size
  236. self.org_vocab_size_padded = pad_vocab_size(
  237. self.org_vocab_size, self.padding_size
  238. )
  239. self.num_embeddings_padded = pad_vocab_size(
  240. self.org_vocab_size_padded + self.num_added_embeddings, self.padding_size
  241. )
  242. # TP=3: 154880 is a multiple of 64 but not of 3. Pad on to a multiple
  243. # of padding_size * tp_size (the padded rows are masked like any other
  244. # vocab padding). Sizes that already split evenly are unchanged.
  245. if self.org_vocab_size_padded % self.tp_size or (
  246. self.num_embeddings_padded % self.tp_size
  247. ):
  248. step = self.padding_size * self.tp_size
  249. self.org_vocab_size_padded = pad_vocab_size(self.org_vocab_size_padded, step)
  250. self.num_embeddings_padded = pad_vocab_size(
  251. self.org_vocab_size_padded + self.num_added_embeddings, step
  252. )
  253. assert self.org_vocab_size_padded <= self.num_embeddings_padded
  254. self.shard_indices = self._get_indices(
  255. self.num_embeddings_padded,
  256. self.org_vocab_size_padded,
  257. self.num_embeddings,
  258. self.org_vocab_size,
  259. tp_rank,
  260. self.tp_size,
  261. )
  262. self.embedding_dim = embedding_dim
  263. # Divide the weight matrix along the vocabulary dimension.
  264. self.num_embeddings_per_partition = divide(
  265. self.num_embeddings_padded, self.tp_size
  266. )
  267. # Quantization methods share the same weight factory as linear layers,
  268. # so setup standard linear metadata.
  269. self.input_size = self.input_size_per_partition = embedding_dim
  270. self.output_size = self.num_embeddings_padded
  271. self.output_size_per_partition = self.num_embeddings_per_partition
  272. self.output_partition_sizes = [self.output_size_per_partition]
  273. self.prefix = prefix
  274. # Avoid overriding a preselected model-specific method with generic
  275. # config-based dispatch.
  276. if quant_method is None and quant_config is not None:
  277. quant_method = resolve_quant_method(quant_config, self, prefix=prefix)
  278. if quant_method is None:
  279. quant_method = UnquantizedEmbeddingMethod()
  280. # If we are making an embedding layer, then our quantization linear
  281. # method must implement the embedding operation. If we are another
  282. # layer type like ParallelLMHead, this is not important.
  283. is_embedding_layer = not isinstance(self, ParallelLMHead)
  284. quant_method_implements_embedding = method_has_implemented_embedding(
  285. type(quant_method)
  286. )
  287. if is_embedding_layer and not quant_method_implements_embedding:
  288. raise NotImplementedError(
  289. f"The class {type(quant_method).__name__} must implement "
  290. "the 'embedding' method, see UnquantizedEmbeddingMethod."
  291. )
  292. self.quant_method: QuantizeMethodBase = quant_method
  293. if params_dtype is None:
  294. params_dtype = torch.get_default_dtype()
  295. self.params_dtype = params_dtype
  296. assert (
  297. self.shard_indices.num_elements_padded == self.num_embeddings_per_partition
  298. )
  299. self.num_org_embeddings_per_partition = (
  300. self.shard_indices.org_vocab_end_index
  301. - self.shard_indices.org_vocab_start_index
  302. )
  303. self.num_added_embeddings_per_partition = (
  304. self.shard_indices.added_vocab_end_index
  305. - self.shard_indices.added_vocab_start_index
  306. )
  307. # The fused kernel masks, shifts and gathers in one pass; it assumes a
  308. # plain row-major shard, so it only applies to unquantized weights.
  309. self.use_fused_embedding = (
  310. self.tp_size > 1
  311. and current_platform.is_cuda()
  312. and isinstance(quant_method, UnquantizedEmbeddingMethod)
  313. )
  314. self.quant_method.create_weights(
  315. self,
  316. self.input_size_per_partition,
  317. self.output_partition_sizes,
  318. self.input_size,
  319. self.output_size,
  320. params_dtype=params_dtype,
  321. weight_loader=self.weight_loader,
  322. )
  323. self.update_param_tp_status()
  324. def update_param_tp_status(self):
  325. for param in self.parameters():
  326. if isinstance(param, BasevLLMParameter):
  327. param.tp_rank = self.tp_rank
  328. param.tp_size = self.tp_size
  329. @classmethod
  330. def _get_indices(
  331. cls,
  332. vocab_size_padded: int,
  333. org_vocab_size_padded: int,
  334. vocab_size: int,
  335. org_vocab_size: int,
  336. tp_rank: int,
  337. tp_size: int,
  338. ) -> VocabParallelEmbeddingShardIndices:
  339. """Get start and end indices for vocab parallel embedding, following the
  340. layout outlined in the class docstring, based on the given tp_rank and
  341. tp_size."""
  342. num_added_embeddings_padded = vocab_size_padded - org_vocab_size_padded
  343. padded_org_vocab_start_index, padded_org_vocab_end_index = (
  344. vocab_range_from_global_vocab_size(org_vocab_size_padded, tp_rank, tp_size)
  345. )
  346. padded_added_vocab_start_index, padded_added_vocab_end_index = (
  347. vocab_range_from_global_vocab_size(
  348. num_added_embeddings_padded, tp_rank, tp_size, offset=org_vocab_size
  349. )
  350. )
  351. # remove padding
  352. org_vocab_start_index = min(padded_org_vocab_start_index, org_vocab_size)
  353. org_vocab_end_index = min(padded_org_vocab_end_index, org_vocab_size)
  354. added_vocab_start_index = min(padded_added_vocab_start_index, vocab_size)
  355. added_vocab_end_index = min(padded_added_vocab_end_index, vocab_size)
  356. return VocabParallelEmbeddingShardIndices(
  357. padded_org_vocab_start_index,
  358. padded_org_vocab_end_index,
  359. padded_added_vocab_start_index,
  360. padded_added_vocab_end_index,
  361. org_vocab_start_index,
  362. org_vocab_end_index,
  363. added_vocab_start_index,
  364. added_vocab_end_index,
  365. )
  366. def get_sharded_to_full_mapping(self) -> list[int] | None:
  367. """Get a mapping that can be used to reindex the gathered
  368. logits for sampling.
  369. During sampling, we gather logits from all ranks. The relationship
  370. of index->token_id will follow the same format as outlined in the class
  371. docstring. However, after the gather, we want to reindex the final
  372. logits tensor to map index->token_id one-to-one (the index is always
  373. equal the token_id it corresponds to). The indices returned by this
  374. method allow us to do that.
  375. """
  376. if self.tp_size < 2:
  377. return None
  378. base_embeddings: list[int] = []
  379. added_embeddings: list[int] = []
  380. padding: list[int] = []
  381. for tp_rank in range(self.tp_size):
  382. shard_indices = self._get_indices(
  383. self.num_embeddings_padded,
  384. self.org_vocab_size_padded,
  385. self.num_embeddings,
  386. self.org_vocab_size,
  387. tp_rank,
  388. self.tp_size,
  389. )
  390. range_start = self.num_embeddings_per_partition * tp_rank
  391. range_end = self.num_embeddings_per_partition * (tp_rank + 1)
  392. base_embeddings.extend(
  393. range(range_start, range_start + shard_indices.num_org_elements)
  394. )
  395. padding.extend(
  396. range(
  397. range_start + shard_indices.num_org_elements,
  398. range_start + shard_indices.num_org_elements_padded,
  399. )
  400. )
  401. added_embeddings.extend(
  402. range(
  403. range_start + shard_indices.num_org_elements_padded,
  404. range_start
  405. + shard_indices.num_org_elements_padded
  406. + shard_indices.num_added_elements,
  407. )
  408. )
  409. padding.extend(
  410. range(
  411. range_start
  412. + shard_indices.num_org_elements_padded
  413. + shard_indices.num_added_elements,
  414. range_start
  415. + shard_indices.num_org_elements_padded
  416. + shard_indices.num_added_elements_padded,
  417. )
  418. )
  419. assert (
  420. range_start
  421. + shard_indices.num_org_elements_padded
  422. + shard_indices.num_added_elements_padded
  423. == range_end
  424. )
  425. ret = base_embeddings + added_embeddings + padding
  426. assert len(ret) == self.num_embeddings_padded
  427. return ret
  428. def weight_loader(self, param: Parameter, loaded_weight: torch.Tensor):
  429. output_dim = getattr(param, "output_dim", None)
  430. packed_dim = getattr(param, "packed_dim", None)
  431. # Parameters without an output dimension are copied onto all GPUs.
  432. if output_dim is None:
  433. if (
  434. loaded_weight.ndim == 0
  435. and param.data.ndim == 1
  436. and param.data.numel() == 1
  437. ):
  438. loaded_weight = loaded_weight.reshape(1)
  439. assert param.data.shape == loaded_weight.shape
  440. param.data.copy_(loaded_weight)
  441. return
  442. # Shard indexes for loading the weight
  443. start_idx = self.shard_indices.org_vocab_start_index
  444. shard_size = self.shard_indices.org_vocab_end_index - start_idx
  445. # If param packed on the same dim we are sharding on, then
  446. # need to adjust offsets of loaded weight by pack_factor.
  447. if packed_dim is not None and packed_dim == output_dim:
  448. packed_factor = (
  449. param.packed_factor
  450. if isinstance(param, BasevLLMParameter)
  451. else param.pack_factor
  452. )
  453. assert loaded_weight.shape[output_dim] == (
  454. self.org_vocab_size // param.packed_factor
  455. )
  456. start_idx = start_idx // packed_factor
  457. shard_size = shard_size // packed_factor
  458. else:
  459. assert loaded_weight.shape[output_dim] == self.org_vocab_size
  460. # Copy the data. Select chunk corresponding to current shard.
  461. loaded_weight = loaded_weight.narrow(output_dim, start_idx, shard_size)
  462. param[: loaded_weight.shape[0]].data.copy_(loaded_weight)
  463. param[loaded_weight.shape[0] :].data.fill_(0)
  464. def forward(self, input_):
  465. if self.tp_size == 1:
  466. return self.quant_method.embedding(self, input_.long())
  467. if self.use_fused_embedding:
  468. output_parallel = ops.vocab_parallel_embedding(
  469. input_ if input_.ndim == 1 else input_.reshape(-1),
  470. self.weight,
  471. self.shard_indices.org_vocab_start_index,
  472. self.shard_indices.org_vocab_end_index,
  473. self.shard_indices.num_org_vocab_padding,
  474. self.shard_indices.added_vocab_start_index,
  475. self.shard_indices.added_vocab_end_index,
  476. )
  477. if input_.ndim != 1:
  478. output_parallel = output_parallel.view(
  479. *input_.shape, self.embedding_dim
  480. )
  481. else:
  482. masked_input, input_mask = get_masked_input_and_mask(
  483. input_,
  484. self.shard_indices.org_vocab_start_index,
  485. self.shard_indices.org_vocab_end_index,
  486. self.shard_indices.num_org_vocab_padding,
  487. self.shard_indices.added_vocab_start_index,
  488. self.shard_indices.added_vocab_end_index,
  489. )
  490. output_parallel = self.quant_method.embedding(self, masked_input.long())
  491. if output_parallel.dtype in (
  492. torch.float8_e4m3fn,
  493. torch.float8_e5m2,
  494. ):
  495. # Each vocab token has one owner, so FP8 bytes can use int8 SUM.
  496. comm_output = output_parallel.view(torch.int8)
  497. comm_output.masked_fill_(input_mask.unsqueeze(-1), 0)
  498. output = (
  499. self.parallel_group.all_reduce(comm_output)
  500. if self.parallel_group is not None
  501. else tensor_model_parallel_all_reduce(comm_output)
  502. )
  503. return output.view(output_parallel.dtype)
  504. output_parallel.masked_fill_(input_mask.unsqueeze(-1), 0)
  505. # Reduce across all the model parallel GPUs.
  506. if self.parallel_group is not None:
  507. return self.parallel_group.all_reduce(output_parallel)
  508. return tensor_model_parallel_all_reduce(output_parallel)
  509. def extra_repr(self) -> str:
  510. s = f"num_embeddings={self.num_embeddings}"
  511. s += f", num_embeddings_per_partition={self.num_embeddings_per_partition}"
  512. s += f", embedding_dim={self.embedding_dim}"
  513. s += f", org_vocab_size={self.org_vocab_size}"
  514. s += f", num_embeddings_padded={self.num_embeddings_padded}"
  515. s += f", tp_size={self.tp_size}"
  516. return s
  517. # --8<-- [start:parallel_lm_head]
  518. @PluggableLayer.register("parallel_lm_head")
  519. class ParallelLMHead(VocabParallelEmbedding):
  520. """Parallelized LM head.
  521. Output logits weight matrices used in the Sampler. The weight and bias
  522. tensors are padded to make sure they are divisible by the number of
  523. model parallel GPUs.
  524. Args:
  525. num_embeddings: vocabulary size.
  526. embedding_dim: size of hidden state.
  527. bias: whether to use bias.
  528. params_dtype: type of the parameters.
  529. org_num_embeddings: original vocabulary size (without LoRA).
  530. padding_size: padding size for the vocabulary.
  531. disable_tp: If true, tensor parallelism will be disabled for this layer.
  532. """
  533. # --8<-- [end:parallel_lm_head]
  534. def __init__(
  535. self,
  536. num_embeddings: int,
  537. embedding_dim: int,
  538. bias: bool = False,
  539. params_dtype: torch.dtype | None = None,
  540. org_num_embeddings: int | None = None,
  541. padding_size: int = DEFAULT_VOCAB_PADDING_SIZE,
  542. quant_config: QuantizationConfig | None = None,
  543. prefix: str = "",
  544. *,
  545. disable_tp: bool = False,
  546. ):
  547. self.has_bias = bias
  548. super().__init__(
  549. num_embeddings,
  550. embedding_dim,
  551. params_dtype,
  552. org_num_embeddings,
  553. padding_size,
  554. quant_config,
  555. prefix,
  556. disable_tp=disable_tp,
  557. )
  558. self.quant_config = quant_config
  559. if bias:
  560. self._register_bias()
  561. else:
  562. self.register_parameter("bias", None)
  563. def _register_bias(self):
  564. data = torch.empty(self.num_embeddings_per_partition, dtype=self.params_dtype)
  565. self.bias = Parameter(data, requires_grad=False)
  566. weight_attrs = dict(output_dim=0, weight_loader=self.weight_loader)
  567. set_weight_attrs(weight=self.bias, weight_attrs=weight_attrs)
  568. def tie_weights(self, embed_tokens: VocabParallelEmbedding):
  569. """Tie the weights with word embeddings."""
  570. return self.quant_method.tie_weights(self, embed_tokens)
  571. def forward(self, input_):
  572. del input_
  573. raise RuntimeError("LMHead's weights should be used in the sampler.")