| import os |
| import logging |
| import random |
| import pytest |
| import torch |
| import torch.distributed as dist |
| from transformers import AutoTokenizer, AutoConfig |
|
|
| from vllm import distributed |
| from vllm.config import ParallelConfig, VllmConfig, set_current_vllm_config, get_current_vllm_config |
|
|
| from dinfer.model import LLaDAModelLM, LLaDAMoeModelLM |
| from dinfer import BlockWiseDiffusionLLM, ThresholdParallelDecoder, HierarchyDecoder |
| from dinfer import DiffusionLLMServing, SamplingParams |
| from dinfer.decoding.utils import BlockIteratorFactory |
|
|
| LLADA_MODEL_PATH = "/mnt/infra/myx/models/LLaDA-1.5/" |
| MOE_MODEL_PATH = '/mnt/infra/dulun.dl/models/LLaDA-MoE/fusemoe/step45567_converted_hf_fusemoe' |
|
|
| def get_prompts(tokenizer, mask_id, device, num=1): |
| prompt = "Lily can run 12 kilometers per hour for 4 hours. After that, she can run 6 kilometers per hour. How many kilometers can she run in 8 hours? " |
| m = [{"role": "user", "content": prompt}, ] |
| prompt = tokenizer.apply_chat_template(m, add_generation_prompt=True, tokenize=False) |
| input_ids1 = torch.tensor(tokenizer(prompt)['input_ids']).to(device).unsqueeze(0) |
| len1 = input_ids1.shape[1] |
|
|
| if num == 2: |
| prompt = "Lily can run 12 kilometers per hour for 4 hours. How many kilometers can she run in 4 hours? " |
| m = [{"role": "user", "content": prompt}, ] |
| prompt = tokenizer.apply_chat_template(m, add_generation_prompt=True, tokenize=False) |
| input_ids2 = torch.tensor(tokenizer(prompt)['input_ids']).to(device).unsqueeze(0) |
| len2 = input_ids2.shape[1] |
| ret = torch.zeros(2, max(len1, len2), dtype=input_ids1.dtype) |
| ret[0, 0:len1] = input_ids1 |
| ret[1, 0:len2] = input_ids2 |
| else: |
| ret = input_ids1 |
|
|
| return ret |
|
|
|
|
| @pytest.fixture(scope="function") |
| def setup_llada_reference(): |
| """ |
| Sets up the standard LLaDA model to generate a ground-truth reference |
| before running the server. |
| """ |
| |
| if 'PYTEST_XDIST_WORKER' in os.environ: |
| worker_num = int(os.environ['PYTEST_XDIST_WORKER'].replace('gw', '')) |
| gpu_id = worker_num % torch.cuda.device_count() |
| else: |
| gpu_id = 0 |
| |
| device = torch.device(gpu_id) |
| torch.cuda.set_device(gpu_id) |
| print(f"[test_serving] Initializing LLaDA Reference on GPU {gpu_id}") |
|
|
| |
| os.environ['MASTER_ADDR'] = 'localhost' |
| os.environ['MASTER_PORT'] = str(40000 + random.randint(0, 1000) + gpu_id) |
| |
| try: |
| distributed.init_distributed_environment(1, 0, 'env://', 0, 'nccl') |
| except (RuntimeError, AssertionError) as e: |
| print(f"Distributed environment already initialized: {e}") |
| |
| try: |
| distributed.initialize_model_parallel(1, backend='nccl') |
| except (RuntimeError, AssertionError) as e: |
| print(f"Model parallel already initialized: {e}") |
|
|
| |
| with set_current_vllm_config(VllmConfig()): |
| config = AutoConfig.from_pretrained(LLADA_MODEL_PATH, trust_remote_code=True, local_files_only=True) |
| config.flash_attention = True |
| config.train_max_sequence_length = 4096 |
| |
| model = LLaDAModelLM.from_pretrained(LLADA_MODEL_PATH, torch_dtype=torch.bfloat16, config=config).eval() |
| model = model.to(device) |
| |
| decoder = ThresholdParallelDecoder(gpu_id, threshold=0.9, use_float64=True) |
| tokenizer = AutoTokenizer.from_pretrained(LLADA_MODEL_PATH, trust_remote_code=True, local_files_only=True) |
| |
| input_ids = get_prompts(tokenizer, mask_id=126336, device=device) |
| |
| yield model, decoder, tokenizer, input_ids, device |
| |
| |
| print(f"[test_serving] Cleaning up LLaDA Reference on GPU {gpu_id}") |
| del model |
| del decoder |
| torch.cuda.empty_cache() |
| try: |
| distributed.destroy_model_parallel() |
| distributed.destroy_distributed_environment() |
| except: |
| pass |
|
|
| @pytest.fixture(scope="function") |
| def setup_moe_reference(): |
| """ |
| Sets up the MoE model to generate a ground-truth reference |
| before running the server. |
| """ |
| if 'PYTEST_XDIST_WORKER' in os.environ: |
| worker_num = int(os.environ['PYTEST_XDIST_WORKER'].replace('gw', '')) |
| gpu_id = worker_num % torch.cuda.device_count() |
| else: |
| gpu_id = 0 |
| |
| device = torch.device(gpu_id) |
| torch.cuda.set_device(gpu_id) |
| print(f"[test_serving] Initializing MoE Reference on GPU {gpu_id}") |
| |
| os.environ['MASTER_ADDR'] = 'localhost' |
| os.environ['MASTER_PORT'] = str(50000 + random.randint(0, 1000) + gpu_id) |
| |
| try: |
| distributed.init_distributed_environment(1, 0, 'env://', 0, 'nccl') |
| except (RuntimeError, AssertionError) as e: |
| print(f"Distributed environment already initialized: {e}") |
| |
| try: |
| distributed.initialize_model_parallel(1, backend='nccl') |
| except (RuntimeError, AssertionError) as e: |
| print(f"Model parallel already initialized: {e}") |
| |
| parallel_config = ParallelConfig(enable_expert_parallel=True) |
| with set_current_vllm_config(VllmConfig(parallel_config=parallel_config)): |
| model_config = AutoConfig.from_pretrained(MOE_MODEL_PATH, trust_remote_code=True, local_files_only=True) |
| model = LLaDAMoeModelLM(config=model_config).eval() |
| model.load_weights(MOE_MODEL_PATH, torch_dtype=torch.bfloat16) |
| model = model.to(device) |
| |
| decoder = ThresholdParallelDecoder(0, threshold=0.9, mask_id=156895, eos_id=156892, use_float64=True) |
| tokenizer = AutoTokenizer.from_pretrained(MOE_MODEL_PATH, trust_remote_code=True, local_files_only=True) |
| input_ids = get_prompts(tokenizer, mask_id=156895, device=device) |
| |
| yield model, decoder, tokenizer, input_ids, device |
| |
| print(f"[test_serving] Cleaning up MoE Reference on GPU {gpu_id}") |
| del model |
| del decoder |
| torch.cuda.empty_cache() |
| try: |
| distributed.destroy_model_parallel() |
| distributed.destroy_distributed_environment() |
| except: |
| pass |
|
|
|
|
| def test_llada_server(setup_llada_reference): |
| model, decoder, tokenizer, input_ids, device = setup_llada_reference |
| print('test serving of standard diffusion LLaDA') |
| |
| |
| params = SamplingParams(temperature=0, threshold=0.9, mask_id=126336, eos_id=126081, early_stop=True, cache='', cont_weight=0, enable_torch_compile=True, use_bd=False) |
| dllm = BlockWiseDiffusionLLM(model, decoder, BlockIteratorFactory(), early_stop=True) |
| res1 = dllm.generate(input_ids, gen_length=256, block_length=32).cpu() |
| |
| del model |
| torch.cuda.empty_cache() |
|
|
| |
| print('Test serving: DP == 1 and TPEP == 1') |
| llm = DiffusionLLMServing(model=LLADA_MODEL_PATH, model_type='llada', backend='vllm', sample_params=params, num_gpus=1, server_port=random.randint(40000, 50000)) |
| |
| try: |
| res = llm.generate(input_ids, gen_length=256, block_length=32) |
| finally: |
| llm.stop_serving() |
| |
| assert res.shape == res1.shape |
| res1 = res1.to(res.device) |
| assert torch.all(res == res1) |
|
|
| def test_moe_server(setup_moe_reference): |
| print('test serving of diffusion-MOE') |
| model, decoder, tokenizer, input_ids, device = setup_moe_reference |
| params = SamplingParams(temperature=0, threshold=0.9, mask_id=156895, eos_id=156892, early_stop=True, cache='', cont_weight=0, enable_torch_compile=False, use_bd=False) |
|
|
| |
| |
| parallel_config = ParallelConfig(enable_expert_parallel=True) |
| with set_current_vllm_config(VllmConfig(parallel_config=parallel_config)): |
| dllm = BlockWiseDiffusionLLM(model, decoder, BlockIteratorFactory(), early_stop=True) |
| res1 = dllm.generate(input_ids, gen_length=256, block_length=32).cpu() |
| |
| |
| del model |
| torch.cuda.empty_cache() |
|
|
| |
| print('Test serving: DP == 1 and TPEP == 1') |
| llm = DiffusionLLMServing(model=MOE_MODEL_PATH, model_type='llada-moe', backend='vllm', sample_params=params, num_gpus=1, server_port=random.randint(50000, 60000)) |
| try: |
| res = llm.generate(input_ids, gen_length=256, block_length=32) |
| assert res.shape == res1.shape |
| res1 = res1.to(res.device) |
| assert torch.all(res == res1) |
| finally: |
| llm.stop_serving() |
|
|
| |
| input_ids2 = torch.cat([input_ids, input_ids]) |
| print('Test serving: DP == 2 and TPEP == 1') |
| llm = DiffusionLLMServing(model=MOE_MODEL_PATH, model_type='llada-moe', backend='vllm', sample_params=params, num_gpus=2, dp_size=2, tpep_size=1, server_port=random.randint(50000, 60000)) |
| try: |
| res2 = llm.generate(input_ids2, gen_length=256, block_length=32) |
| |
| assert torch.all(res2[0][res2[0] != 156892] == res[0][res[0] != 156892]) |
| finally: |
| llm.stop_serving() |
|
|
| |
| print('Test serving: DP == 2 and TPEP == 2 (2 GPUs)') |
| llm = DiffusionLLMServing(model=MOE_MODEL_PATH, model_type='llada-moe', backend='vllm', sample_params=params, num_gpus=2, dp_size=1, tpep_size=2, server_port=random.randint(50000, 60000)) |
| try: |
| res = llm.generate(input_ids, gen_length=256, block_length=32) |
| finally: |
| llm.stop_serving() |
|
|
| print('Test serving: DP == 2 and TPEP == 2 (4 GPUs)') |
| input_ids2 = torch.cat([input_ids, input_ids]) |
| llm = DiffusionLLMServing(model=MOE_MODEL_PATH, model_type='llada-moe', backend='vllm', sample_params=params, num_gpus=4, dp_size=2, tpep_size=2, server_port=random.randint(40000, 50000)) |
| try: |
| res2 = llm.generate(input_ids2, gen_length=256, block_length=32) |
| assert torch.all(res2[0][res2[0] != 156892] == res[0][res[0] != 156892]) |
| finally: |
| llm.stop_serving() |