| 1 | # SPDX-License-Identifier: Apache-2.0 |
| 2 | # SPDX-FileCopyrightText: Copyright contributors to the vLLM project |
| 3 | import argparse |
| 4 | import inspect |
| 5 | |
| 6 | from vllm.benchmarks.mm_processor import add_cli_args, main |
| 7 | from vllm.entrypoints.cli.benchmark.base import BenchmarkSubcommandBase |
| 8 | from vllm.utils.argparse_utils import FlexibleArgumentParser |
| 9 | |
| 10 | |
| 11 | class BenchmarkMMProcessorSubcommand(BenchmarkSubcommandBase): |
| 12 | r"""`vllm bench mm-processor` profiles the multimodal input processor pipeline of |
| 13 | vision-language models. It measures per-stage latency from the HuggingFace |
| 14 | processor through to the encoder forward pass, helping you identify |
| 15 | preprocessing bottlenecks and understand how different image resolutions or |
| 16 | item counts affect end-to-end request time. |
| 17 | |
| 18 | The benchmark supports two data sources: synthetic random multimodal inputs |
| 19 | (`random-mm`) and HuggingFace datasets (`hf`). Warmup requests are run before |
| 20 | measurement to ensure stable results. |
| 21 | |
| 22 | ## Quick Start |
| 23 | |
| 24 | ```bash |
| 25 | vllm bench mm-processor \ |
| 26 | --model Qwen/Qwen2-VL-7B-Instruct \ |
| 27 | --dataset-name random-mm \ |
| 28 | --num-prompts 50 \ |
| 29 | --random-input-len 300 \ |
| 30 | --random-output-len 40 \ |
| 31 | --random-mm-base-items-per-request 2 \ |
| 32 | --random-mm-limit-mm-per-prompt '{"image": 3, "video": 0}' \ |
| 33 | --random-mm-bucket-config '{(256, 256, 1): 0.7, (720, 1280, 1): 0.3}' |
| 34 | ``` |
| 35 | |
| 36 | ## Measured Stages |
| 37 | |
| 38 | | Stage | Description | |
| 39 | | ----- | ----------- | |
| 40 | | `get_mm_hashes_secs` | Time spent hashing multimodal inputs | |
| 41 | | `get_cache_missing_items_secs` | Time spent looking up the processor cache | |
| 42 | | `apply_hf_processor_secs` | Time spent in the HuggingFace processor | |
| 43 | | `merge_mm_kwargs_secs` | Time spent merging multimodal kwargs | |
| 44 | | `apply_prompt_updates_secs` | Time spent updating prompt tokens | |
| 45 | | `preprocessor_total_secs` | Total preprocessing time | |
| 46 | | `encoder_forward_secs` | Time spent in the encoder model forward pass | |
| 47 | | `num_encoder_calls` | Number of encoder invocations per request | |
| 48 | |
| 49 | The benchmark also reports end-to-end latency (TTFT + decode time) per |
| 50 | request. Use `--metric-percentiles` to select which percentiles to report |
| 51 | (default: p99) and `--output-json` to save results. |
| 52 | |
| 53 | For more examples (HF datasets, warmup, JSON output), see the |
| 54 | [multimodal processor benchmark guide](https://docs.vllm.ai/en/latest/benchmarking/cli/#multimodal-processor-benchmark). |
| 55 | """ |
| 56 | |
| 57 | name = "mm-processor" |
| 58 | help = "Benchmark multimodal processor latency across different configurations." |
| 59 | |
| 60 | @classmethod |
| 61 | def add_cli_args(cls, parser: FlexibleArgumentParser) -> None: |
| 62 | # The class docstring is the page overview / `--help` description. |
| 63 | if cls.__doc__: |
| 64 | parser.description = inspect.cleandoc(cls.__doc__) |
| 65 | add_cli_args(parser) |
| 66 | |
| 67 | @staticmethod |
| 68 | def cmd(args: argparse.Namespace) -> None: |
| 69 | main(args) |