main
py 91 lines 3.11 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 # unit test for `examples/features/torchrun/torchrun_example_offline.py`
5 import os
6 import random
7
8 import torch
9 import torch.distributed as dist
10
11 import vllm.envs as envs
12 from vllm import LLM, SamplingParams
13 from vllm.distributed.parallel_state import get_tp_group, get_world_group
14
15 # By default, let PyTorch choose the WORLD backend for the current device
16 # type (legacy lazy-init path). When VLLM_DISTRIBUTED_USE_SPLIT_GROUP=1,
17 # use the explicit eager-init pattern required by `split_group` (mixed
18 # cpu:gloo,cuda:nccl backend + device_id binding).
19 if envs.VLLM_DISTRIBUTED_USE_SPLIT_GROUP:
20 local_rank = int(os.environ["LOCAL_RANK"])
21 torch.accelerator.set_device_index(local_rank)
22 dist.init_process_group(
23 backend="cpu:gloo,cuda:nccl",
24 device_id=torch.device(f"cuda:{local_rank}"),
25 )
26 else:
27 dist.init_process_group()
28
29 # Create prompts
30 prompts = [
31 "Hello, my name is",
32 "The president of the United States is",
33 "The capital of France is",
34 "The future of AI is",
35 ] * 10
36 dp_size = int(os.getenv("DP_SIZE", "1"))
37 dp_rank = int(os.getenv("DP_RANK", "0"))
38
39 if dp_size > 1:
40 # distribute the prompts across the data parallel ranks
41 prompts = [prompt for idx, prompt in enumerate(prompts) if idx % dp_size == dp_rank]
42
43 sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
44
45 # set different `gpu_memory_utilization` for different ranks,
46 # to test if all ranks agree on the same kv cache configuration.
47 llm = LLM(
48 model="microsoft/Phi-mini-MoE-instruct",
49 tensor_parallel_size=int(os.getenv("TP_SIZE", "1")),
50 pipeline_parallel_size=int(os.getenv("PP_SIZE", "1")),
51 enable_expert_parallel=int(os.getenv("ENABLE_EP", "0")) == 1,
52 distributed_executor_backend="external_launcher",
53 gpu_memory_utilization=random.uniform(0.8, 0.92),
54 seed=0,
55 max_model_len=1024,
56 max_num_seqs=16,
57 )
58
59 outputs = llm.generate(prompts, sampling_params)
60
61 group = get_world_group() if dp_size == 1 else get_tp_group()
62 cpu_group = group.cpu_group
63 group_rank = dist.get_rank(group=cpu_group)
64
65
66 def test_consistent_across_ranks(obj):
67 if group_rank == 0:
68 dist.broadcast_object_list([obj], src=group.ranks[0], group=cpu_group)
69 else:
70 container = [None]
71 dist.broadcast_object_list(container, src=group.ranks[0], group=cpu_group)
72 assert container[0] == obj
73
74
75 test_consistent_across_ranks(llm.llm_engine.vllm_config.cache_config.num_cpu_blocks)
76 test_consistent_across_ranks(llm.llm_engine.vllm_config.cache_config.num_gpu_blocks)
77
78 # make sure we can access the model parameters from the calling process
79 # of the `LLM` instance.
80 params = list(
81 llm.llm_engine.model_executor.driver_worker.worker.model_runner.model.parameters()
82 )
83 test_consistent_across_ranks(len(params))
84
85 # all ranks should have the same outputs
86 for output in outputs:
87 prompt = output.prompt
88 generated_text = output.outputs[0].text
89 test_consistent_across_ranks(prompt)
90 test_consistent_across_ranks(generated_text)
91 print(f"Rank {group_rank}, Prompt: {prompt!r}, Generated text: {generated_text!r}")