main
py 138 lines 3.93 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import unittest
5
6 import pytest
7 import torch
8
9 from tests.utils import ensure_current_vllm_config, multi_gpu_test
10 from vllm.distributed.parallel_state import (
11 init_distributed_environment,
12 initialize_model_parallel,
13 )
14 from vllm.model_executor.layers.mamba.mamba_mixer2 import Mixer2RMSNormGated
15 from vllm.utils.system_utils import update_environment_variables
16 from vllm.utils.torch_utils import set_random_seed
17
18
19 @multi_gpu_test(num_gpus=2)
20 @pytest.mark.parametrize("batch_size", [8])
21 @pytest.mark.parametrize("seq_len", [128])
22 @pytest.mark.parametrize(
23 "hidden_size_n_groups",
24 [
25 (64, 1),
26 (64, 2),
27 (64, 4), # hidden_size be divisible by num_gpus
28 ],
29 )
30 @pytest.mark.parametrize("dtype", [torch.float16])
31 def test_mixer2_gated_norm_multi_gpu(
32 batch_size: int,
33 seq_len: int,
34 hidden_size_n_groups: tuple[int, int],
35 dtype: torch.dtype,
36 device: str = "cuda",
37 ):
38 hidden_size, n_groups = hidden_size_n_groups
39 num_processes = 2
40
41 def run_torch_spawn(fn, nprocs):
42 # need to use torch.mp.spawn otherwise will have problems with
43 # torch.distributed and cuda
44 torch.multiprocessing.spawn(
45 fn,
46 args=(
47 num_processes,
48 batch_size,
49 seq_len,
50 hidden_size,
51 n_groups,
52 dtype,
53 device,
54 ),
55 nprocs=nprocs,
56 )
57
58 run_torch_spawn(mixer2_gated_norm_tensor_parallel, 2)
59
60
61 def mixer2_gated_norm_tensor_parallel(
62 local_rank: int,
63 world_size: int,
64 batch_size: int,
65 seq_len: int,
66 hidden_size: int,
67 n_groups: int,
68 dtype: torch.dtype,
69 device: str,
70 ):
71 set_random_seed(0)
72
73 device = torch.device(f"cuda:{local_rank}")
74 torch.accelerator.set_device_index(device)
75 torch.set_default_device(device)
76 torch.set_default_dtype(dtype)
77
78 update_environment_variables(
79 {
80 "RANK": str(local_rank),
81 "LOCAL_RANK": str(local_rank),
82 "WORLD_SIZE": str(world_size),
83 "MASTER_ADDR": "localhost",
84 "MASTER_PORT": "12345",
85 }
86 )
87
88 # initialize distributed
89 init_distributed_environment()
90 with ensure_current_vllm_config():
91 initialize_model_parallel(tensor_model_parallel_size=world_size)
92
93 # create random weights an inputs
94 weight = torch.rand((hidden_size,), dtype=dtype, device=device)
95 hidden_states = torch.randn(batch_size, seq_len, hidden_size)
96 gate_states = torch.randn(batch_size, seq_len, hidden_size)
97
98 # create gated-norm with TP
99 mixer = Mixer2RMSNormGated(
100 full_hidden_size=hidden_size,
101 full_n_groups=n_groups,
102 )
103 mixer.weight.weight_loader(mixer.weight, weight) # load
104
105 # create gated-norm without TP to compute reference
106 # - utilize mock patching to disable TP when
107 with (
108 unittest.mock.patch(
109 "vllm.model_executor.layers.mamba.mamba_mixer2."
110 "get_tensor_model_parallel_world_size",
111 return_value=1,
112 ),
113 unittest.mock.patch(
114 "vllm.model_executor.layers.mamba.mamba_mixer2."
115 "get_tensor_model_parallel_rank",
116 return_value=0,
117 ),
118 ):
119 mixer_single_gpu = Mixer2RMSNormGated(
120 full_hidden_size=hidden_size,
121 full_n_groups=n_groups,
122 )
123 # assign weight to single-gpu mixer
124 mixer_single_gpu.weight.data = weight
125
126 # generate and compare
127 N = hidden_size // world_size
128 output = mixer(
129 hidden_states[..., local_rank * N : (local_rank + 1) * N],
130 gate_states[..., local_rank * N : (local_rank + 1) * N],
131 )
132 ref_output = mixer_single_gpu(hidden_states, gate_states)
133 torch.testing.assert_close(
134 output,
135 ref_output[..., local_rank * N : (local_rank + 1) * N],
136 atol=5e-3,
137 rtol=1e-3,
138 )