指标¶
vLLM 提供了一套丰富的指标,以支持 V1 引擎的可观测性和容量规划。
目标¶
- 全面覆盖引擎和请求级别的指标,以辅助生产环境的监控。
- 优先集成 Prometheus,因为我们预计它将在生产环境中使用。
- 提供日志支持(即打印指标到 info 日志),用于临时测试、调试、开发和探索性用例。
背景¶
vLLM 中的指标可以按如下方式分类:
- 服务器级别指标:全局指标,用于跟踪 LLM 引擎的状态和性能。这些通常在 Prometheus 中暴露为 Gauge 或 Counter。
- 请求级别指标:指标,用于跟踪单个请求的特征(例如大小和计时)。这些通常在 Prometheus 中暴露为 Histogram,并且通常是 SRE 监控 vLLM 时将跟踪的 SLO。
其思想模型是,服务器级别指标有助于解释请求级别指标的值。
指标概览¶
v1 指标¶
在 v1 中,通过 Prometheus 兼容的 /metrics 端点公开了大量的指标,使用 vllm: 前缀,例如:
vllm:num_requests_running(Gauge) - 当前运行的请求数量。vllm:kv_cache_usage_perc(Gauge) - 已使用的 KV cache 块的比例(0-1)。vllm:prefix_cache_queries(Counter) - Prefix cache 查询次数。vllm:prefix_cache_hits(Counter) - Prefix cache 命中次数。vllm:prompt_tokens_total(Counter) - 处理过的 Prompt tokens 总数。vllm:generation_tokens_total(Counter) - 生成的 tokens 总数。vllm:request_success_total(Counter) - 完成的请求数量(按结束原因)。vllm:request_prompt_tokens(Histogram) - 输入 Prompt token 数量的直方图。vllm:request_generation_tokens(Histogram) - 生成 token 数量的直方图。vllm:time_to_first_token_seconds(Histogram) - 到达第一个 token 的时间(TTFT)。vllm:inter_token_latency_seconds(Histogram) - Token 之间的延迟。vllm:e2e_request_latency_seconds(Histogram) - 端到端请求延迟。vllm:request_prefill_time_seconds(Histogram) - 请求的预填充时间。vllm:request_decode_time_seconds(Histogram) - 请求的解码时间。
这些在 推理与服务 -> 生产指标 中有记录。
Grafana Dashboard¶
vLLM 还提供了一个 参考示例,展示了如何使用 Prometheus 收集和存储这些指标,并使用 Grafana 进行可视化。
Grafana Dashboard 中显示的指标子集表明了哪些指标特别重要。
vllm:e2e_request_latency_seconds_bucket- 端到端请求延迟(秒)。vllm:prompt_tokens- Prompt tokens。vllm:generation_tokens- Generation tokens。vllm:time_per_output_token_seconds- Token 之间延迟(每输出 token 时间,TPOT)(秒)。vllm:time_to_first_token_seconds- 到达第一个 token 的时间(TTFT)(秒)。vllm:num_requests_running(以及_swapped和_waiting) - RUNNING、WAITING 和 SWAPPED 状态下的请求数量。vllm:kv_cache_usage_perc- vLLM 使用的 cache 块百分比。vllm:request_prompt_tokens- 请求 Prompt 长度。vllm:request_generation_tokens- 请求 Generation 长度。vllm:request_success- 完成的请求数量(按其结束原因):生成了 EOS token 或达到了最大序列长度。vllm:request_queue_time_seconds- 排队时间。vllm:request_prefill_time_seconds- 请求预填充时间。vllm:request_decode_time_seconds- 请求解码时间。vllm:request_max_num_generation_tokens- 序列组的最大生成 token 数量。
请参阅 添加此 Dashboard 的 PR 以获取有关此处所做选择的有趣且有用的背景信息。
Prometheus Client Library¶
Prometheus 支持最初是使用 aioprometheus 库添加的,但很快切换到了 prometheus_client。理由在两个链接的 PR 中都有讨论。
在这些迁移过程中,我们短暂丢失了用于跟踪 HTTP 指标的 MetricsMiddleware,但它后来通过 prometheus_fastapi_instrumentator 重新启用。
$ curl http://0.0.0.0:8000/metrics 2>/dev/null | grep -P '^http_(?!.*(_bucket|_created|_sum)).*'
http_requests_total{handler="/v1/completions",method="POST",status="2xx"} 201.0
http_request_size_bytes_count{handler="/v1/completions"} 201.0
http_response_size_bytes_count{handler="/v1/completions"} 201.0
http_request_duration_highr_seconds_count 201.0
http_request_duration_seconds_count{handler="/v1/completions",method="POST"} 201.0
多进程模式¶
历史上,指标是在引擎核心进程中收集的,并通过多进程模式使其在 API 服务器进程中可用。请参阅 PR #7279。
最近,指标是在 API 服务器进程中收集的,并且仅在 --api-server-count > 1 时使用多进程模式。请参阅 PR #17546 和 API 服务器横向扩展的详细信息。
内置 Python/进程指标¶
以下指标默认受 prometheus_client 支持,但在使用多进程模式时不会暴露:
python_gc_objects_collected_totalpython_gc_objects_uncollectable_totalpython_gc_collections_totalpython_infoprocess_virtual_memory_bytesprocess_resident_memory_bytesprocess_start_time_secondsprocess_cpu_seconds_totalprocess_open_fdsprocess_max_fds
因此,当 --api-server-count > 1 时,这些指标将不可用。这些指标的相关性值得怀疑,因为它们没有汇总构成 vLLM 实例的所有进程的这些统计信息。
指标设计¶
在 "Even Better Observability" 功能中,其中大部分指标设计都在此进行了规划。例如,请参阅 详细路线图。
旧版 PR¶
为了帮助理解指标设计的背景,以下是一些添加了原始、现在已弃用指标的相关 PR:
指标实现 PR¶
作为背景,以下是与指标实现相关的 PR: Issue #10582
- Pull Request #11962
- Pull Request #11973
- Pull Request #10907
- Pull Request #12416
- Pull Request #12478
- Pull Request #12516
- Pull Request #12530
- Pull Request #12561
- Pull Request #12579
- Pull Request #12592
- Pull Request #12644
指标收集¶
在 v1 中,我们希望将计算和开销移出引擎核心进程,以最大限度地减少每次前向传递之间的时间。
V1 EngineCore 设计的整体思路是:
- EngineCore 是内部循环。性能在此处最为关键。
- AsyncLLM 是外部循环。它与 GPU 执行(理想情况下)重叠,因此如果可能,任何“开销”都应该在此处。因此,如果可能,AsyncLLM.output_handler_loop 是指标簿记的理想位置。
我们将通过在前端 API 服务器中收集指标来实现这一点,并根据从引擎核心进程返回给前端的 EngineCoreOutputs 中收集的信息来确定这些指标。
时间间隔计算¶
我们的许多指标是处理请求过程中各种事件之间的时间间隔。最佳实践是使用基于“单调时间”(time.monotonic())而不是“挂钟时间”(time.time())的时间戳来计算时间间隔,因为前者不受系统时钟更改(例如 NTP 引起)的影响。
同样重要的是要注意,单调时钟在进程之间是不同的——每个进程都有自己的参考点。因此,比较来自不同进程的单调时间戳是没有意义的。
因此,为了计算时间间隔,我们必须比较同一进程中的两个单调时间戳。
调度器统计信息¶
引擎核心进程将从调度器收集一些关键统计信息——例如,在上一个调度器传递后已调度或等待的请求数量——并将这些统计信息包含在 EngineCoreOutputs 中。
Engine Core 事件¶
引擎核心还将记录某些每个请求事件的时间戳,以便前端可以计算这些事件之间的时间间隔。
事件是:
QUEUED- 请求被引擎核心接收并添加到调度器队列时。SCHEDULED- 请求首次被安排执行时。PREEMPTED- 为了给其他请求腾出空间而将请求放回等待队列。它将在未来重新安排,并重新开始其预填充阶段。NEW_TOKENS-EngineCoreOutput中包含的输出生成时。由于这是给定迭代中所有请求的通用事件,因此我们使用EngineCoreOutputs上的单个时间戳来记录此事件。
计算出的时间间隔是:
- 队列间隔 -
QUEUED和最近的SCHEDULED之间。 - 预填充间隔 - 最近的
SCHEDULED和随后的第一个NEW_TOKENS之间。 - 解码间隔 - 第一个(最近的
SCHEDULED之后)和最后一个NEW_TOKENS之间。 - 推理间隔 - 最近的
SCHEDULED和最后一个NEW_TOKENS之间。 - Token 间隔 - 相邻
NEW_TOKENS之间。
换句话说:
我们探索了让前端使用前端可见的事件计时来计算这些时间间隔的可能性。然而,前端无法看到 QUEUED 和 SCHEDULED 事件的计时,并且,由于我们需要使用来自同一进程的单调时间戳来计算时间间隔……我们需要引擎核心记录所有这些事件的时间戳。
时间间隔计算与预占¶
当解码过程中发生预占时,由于任何已生成的 token 都会被重用,我们认为预占会影响 token 之间、解码和推理间隔。
当预填充过程中发生预占时(假设此类事件可能发生),我们认为预占会影响到达第一个 token 的时间(time-to-first-token)和预填充间隔。
前端统计信息收集¶
当前端处理单个 EngineCoreOutputs(即来自单个引擎核心迭代的输出)时,它会收集与该迭代相关的各种统计信息:
- 此迭代中生成的新 token 总数。
- 此迭代中完成的预填充所处理的 prompt token 总数。
- 此迭代中安排的任何请求的队列间隔。
- 此迭代中完成的任何请求的预填充间隔。
- 此迭代中包含的所有请求的 token 之间间隔(每输出 token 时间,TPOT)。
- 此迭代中完成预填充的任何请求的到达第一个 token 的时间(TTFT)。然而,我们计算此时间间隔是相对于请求首次由前端接收(
arrival_time)的时间,以考虑输入处理时间。
对于在给定迭代中完成的任何请求,我们还记录:
- 推理和解码间隔 - 相对于上述的调度和第一个 token 事件。
- 端到端延迟 - 前端
arrival_time到前端接收最后一个 token 之间的时间间隔。
KV Cache 驻留指标¶
我们还输出了一个直方图集,描述了采样的 KV cache 块的驻留时间以及它们被重用的频率。采样(--kv-cache-metrics-sample)可以使开销微乎其微;当选择一个块时,我们记录:
lifetime– 分配 ⟶ 驱逐idle before eviction– 最后一次触碰 ⟶ 驱逐reuse gaps– 当块被重用时,触碰之间的暂停时间
这些直接映射到 Prometheus 指标:
vllm:kv_block_lifetime_seconds– 每个采样块存在的时间。vllm:kv_block_idle_before_evict_seconds– 最后一次访问后的空闲尾部。vllm:kv_block_reuse_gap_seconds– 连续触碰之间的时间。
引擎核心仅通过 SchedulerStats 发送原始的驱逐事件;前端会消耗它们,将其转换为 Prometheus 观测值,并在日志记录开启时通过 LLM.get_metrics() 公开相同数据。查看生命周期和空闲时间图表可以轻松发现滞留的 cache 或需要长时间解码才能固定 Prompt 的工作负载。
指标发布 - 日志记录¶
LoggingStatLogger 指标发布器每 5 秒输出一个 INFO 级别的日志消息,包含一些关键指标:
- 当前运行/等待的请求数量。
- 当前 GPU 缓存使用情况。
- 过去 5 秒内的每秒 Prompt tokens 处理量。
- 过去 5 秒内的每秒新 token 生成量。
- 最近 1k kv-cache 块查询的 Prefix cache 命中率。
指标发布 - Prometheus¶
PrometheusStatLogger 指标发布器通过 /metrics HTTP 端点以 Prometheus 兼容的格式提供指标。然后,可以配置 Prometheus 实例轮询此端点(例如,每秒一次),并将其值记录到其时间序列数据库中。Prometheus 通常通过 Grafana 使用,允许这些指标随时间推移进行图形化显示。
Prometheus 支持以下指标类型:
- Counter:一个随时间增加的数值,永不减少,并且通常在 vLLM 实例重启时重置为零。例如,实例生命周期内生成的 token 数量。
- Gauge:一个上下波动的数值,例如当前正在安排执行的请求数量。
- Histogram:一个指标样本的计数,记录在桶中。例如,TTFT 小于 1ms、小于 5ms、小于 10ms、小于 20ms 等的请求数量。
Prometheus 指标也可以被标签化,允许根据匹配的标签组合指标。在 vLLM 中,我们将 model_name 标签添加到每个指标中,其中包含该实例所服务的模型的名称。
示例输出
$ curl http://0.0.0.0:8000/metrics
# HELP vllm:num_requests_running Number of requests in model execution batches.
# TYPE vllm:num_requests_running gauge
vllm:num_requests_running{model_name="meta-llama/Llama-3.1-8B-Instruct"} 8.0
...
# HELP vllm:generation_tokens_total Number of generation tokens processed.
# TYPE vllm:generation_tokens_total counter
vllm:generation_tokens_total{model_name="meta-llama/Llama-3.1-8B-Instruct"} 27453.0
...
# HELP vllm:request_success_total Count of successfully processed requests.
# TYPE vllm:request_success_total counter
vllm:request_success_total{finished_reason="stop",model_name="meta-llama/Llama-3.1-8B-Instruct"} 1.0
vllm:request_success_total{finished_reason="length",model_name="meta-llama/Llama-3.1-8B-Instruct"} 131.0
vllm:request_success_total{finished_reason="abort",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
...
# HELP vllm:time_to_first_token_seconds Histogram of time to first token in seconds.
# TYPE vllm:time_to_first_token_seconds histogram
vllm:time_to_first_token_seconds_bucket{le="0.001",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.005",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.01",model_name="meta-llama/Llama-3.1-8B-Instruct"} 0.0
vllm:time_to_first_token_seconds_bucket{le="0.02",model_name="meta-llama/Llama-3.1-8B-Instruct"} 13.0
vllm:time_to_first_token_seconds_bucket{le="0.04",model_name="meta-llama/Llama-3.1-8B-Instruct"} 97.0
vllm:time_to_first_token_seconds_bucket{le="0.06",model_name="meta-llama/Llama-3.1-8B-Instruct"} 123.0
vllm:time_to_first_token_seconds_bucket{le="0.08",model_name="meta-llama/Llama-3.1-8B-Instruct"} 138.0
vllm:time_to_first_token_seconds_bucket{le="0.1",model_name="meta-llama/Llama-3.1-8B-Instruct"} 140.0
vllm:time_to_first_token_seconds_count{model_name="meta-llama/Llama-3.1-8B-Instruct"} 140.0
注意
选择对用户在广泛用例中最有用的直方图桶并非易事,需要随着时间的推移进行完善。
Cache 配置信息¶
prometheus_client 支持 Info 指标,它等同于一个值永久设置为 1 的 Gauge,但通过标签暴露有趣的键/值对信息。这用于关于一个实例的信息,这些信息不会改变——因此只需要在启动时观察——并允许在 Prometheus 中跨实例进行比较。
我们将此概念用于 vllm:cache_config_info 指标
# HELP vllm:cache_config_info Information of the LLMEngine CacheConfig
# TYPE vllm:cache_config_info gauge
vllm:cache_config_info{block_size="16",cache_dtype="auto",calculate_kv_scales="False",cpu_offload_gb="0",enable_prefix_caching="False",gpu_memory_utilization="0.9",...} 1.0
然而,prometheus_client 在多进程模式下从未支持 Info 指标——由于 不明确的原因。我们只使用一个设置为 1 的 Gauge 指标和 multiprocess_mode="mostrecent" 来代替。
LoRA 指标¶
vllm:lora_requests_info Gauge 在某种程度上是相似的,除了值是当前的挂钟时间,并且每迭代更新一次。
使用的标签名称是
running_lora_adapters:一个按适配器统计的正在使用该适配器的请求数,格式为逗号分隔的字符串。waiting_lora_adapters:类似,但计数的是正在等待调度的请求。max_lora- 静态的“单个批次中 LoRA 的最大数量”配置。
将多个适配器的正在运行/等待计数编码为逗号分隔的字符串似乎非常错误——我们可以使用标签来区分每个适配器的计数。这一点应该重新审视。
请注意,使用了 multiprocess_mode="livemostrecent" ——使用最新的指标,但仅来自当前正在运行的进程。
这已在 拉取请求 #9477 中添加,并且有一个 至少有一位已知用户。如果我们重新审视此设计并弃用旧指标,我们应与下游用户协调,以便他们在移除之前进行迁移。
前缀缓存指标¶
在 问题 #10582 中关于添加前缀缓存指标的讨论产生了一些有趣的观点,这些观点可能与我们处理未来指标的方式有关。
每次查询前缀缓存时,我们都会记录查询的 token 数量以及缓存中存在的查询 token 数量(即命中数)。
然而,我们感兴趣的指标是命中率——即每次查询的命中数。
在日志记录的情况下,我们期望用户最好通过计算最近 N 次查询(目前固定为 1k 次最近查询的间隔)的命中率来获得最佳服务。
但在 Prometheus 的情况下,我们应该利用 Prometheus 的时间序列特性,允许用户计算他们选择的间隔内的命中率。例如,一个计算过去 5 分钟命中间隔的 PromQL 查询
为了实现这一点,我们应该将查询和命中记录为 Prometheus 中的计数器,而不是将命中率记录为 gauge。
已弃用指标¶
如何弃用¶
弃用指标不应轻视。用户可能没有注意到某个指标已被弃用,并且当它突然(从他们的角度来看)被移除时,即使有等效的指标供他们使用,也会造成很大的不便。
例如,请参阅 vllm:avg_prompt_throughput_toks_per_s 如何被 弃用(带有代码注释), 移除,并且 被用户发现。
总的来说
- 我们应该谨慎对待弃用指标,尤其是在很难预测用户影响的情况下。
- 我们应该在包含在 `/metrics` 输出中的帮助字符串中包含一个醒目的弃用通知。
- 我们应该在面向用户的文档和发行说明中列出已弃用的指标。
- 我们应该考虑将已弃用的指标隐藏在一个 CLI 参数后面,以便为管理员提供一个 逃生通道,在删除它们之前保留一段时间。
请参阅项目的 弃用策略。
未实现 - vllm:tokens_total¶
由 拉取请求 #4464 添加,但显然从未实现。这个可以删除。
重复 - 排队时间¶
vllm:time_in_queue_requests Histogram 指标由 拉取请求 #9659 添加,其计算结果为
self.metrics.first_scheduled_time = now
self.metrics.time_in_queue = now - self.metrics.arrival_time
两周后, 拉取请求 #4464 添加了 vllm:request_queue_time_seconds,使我们剩下
if seq_group.is_finished():
if (seq_group.metrics.first_scheduled_time is not None and
seq_group.metrics.first_token_time is not None):
time_queue_requests.append(
seq_group.metrics.first_scheduled_time -
seq_group.metrics.arrival_time)
...
if seq_group.metrics.time_in_queue is not None:
time_in_queue_requests.append(
seq_group.metrics.time_in_queue)
这看起来是重复的,其中一个应该被移除。后者被 Grafana 面板使用,所以我们应该弃用或移除前者。
前缀缓存命中率¶
见上文——我们现在暴露的是“queries”和“hits”计数器,而不是“hit rate”gauge。
KV 缓存卸载¶
两个旧指标与已不再相关的“已交换”抢占模式有关 v1
vllm:num_requests_swappedvllm:cpu_cache_usage_perc
在此模式下,当请求被抢占时(例如,为完成其他请求腾出 KV 缓存空间),我们会将 kv 缓存块交换到 CPU 内存。这也被称为“KV 缓存卸载”,并通过 --swap-space 和 --preemption-mode 进行配置。
历史上, vLLM 很早就支持束搜索。SequenceGroup 封装了共享相同提示 kv 块的 N 个序列的想法。这使得请求之间可以共享 KV 缓存块,并使用写时复制进行分支。CPU 交换的目的是为了这些类似束搜索的场景。
后来,引入了前缀缓存的概念,它允许 KV 缓存块被隐式共享。事实证明,这比 CPU 交换更好(开销为零),因为块可以按需缓慢地逐出,并且被逐出的提示部分可以重新计算。
SequenceGroup 在 V1 中被移除,尽管需要一个替代品来支持“并行采样”(n>1)。 束搜索已移出核心。有很多复杂代码是为了一个非常不常见的特性。
在 V1 中,随着前缀缓存变得更好(零开销)并且因此默认启用,抢占和重新计算策略应该工作得更好。
未来工作¶
并行采样¶
一些旧指标仅与“并行采样”相关。这是请求中的 n 参数用于从同一提示请求多个完成。
作为在 拉取请求 #10980 中添加并行采样支持的一部分,我们也应该添加这些指标。
vllm:request_params_n(Histogram)
观察每个已完成请求的 'n' 参数值。
vllm:request_max_num_generation_tokens(Histogram)
观察每个已完成序列组中所有序列的最大输出长度。在没有并行采样的情况下,这等同于 vllm:request_generation_tokens。
推断式解码¶
一些旧指标特定于“推断式解码”。这是我们使用更快、近似的方法或模型生成候选 token,然后用更大的模型验证这些 token。
vllm:spec_decode_draft_acceptance_rate(Gauge)vllm:spec_decode_efficiency(Gauge)vllm:spec_decode_num_accepted_tokens(Counter)vllm:spec_decode_num_draft_tokens(Counter)vllm:spec_decode_num_emitted_tokens(Counter)
有一个正在审查的 PR ( 拉取请求 #12193) 来为 v1 添加“提示查找(ngram)”推断式解码。其他技术将随后跟进。我们应该在此上下文中重新审视这些指标。
注意
我们可能应该将接受率暴露为单独的已接受和草稿计数器,就像我们处理前缀缓存命中率一样。效率可能也需要类似的待遇。
自动缩放和负载均衡¶
我们指标的一个常见用例是支持 vLLM 实例的自动缩放。
有关 Kubernetes 服务工作组 的相关讨论,请参阅
这是一个不平凡的话题。考虑 Rob 的评论
我认为这个指标应该专注于尝试估计什么将导致平均请求长度大于每秒查询次数的最大并发度……因为这才是真正会“饱和”服务器的。
一个明确的目标是,我们应该公开检测到这种饱和点所需的指标,以便管理员可以基于这些指标实施自动缩放规则。然而,为了做到这一点,我们需要清楚地了解管理员(和自动化监控系统)应如何判断一个实例接近饱和。
为了识别模型服务器计算的饱和点(即我们无法通过更高的请求速率获得更多吞吐量,但开始产生额外延迟的转折点),以便我们有效地进行自动缩放?
指标命名¶
我们对指标命名的处理可能值得重新审视
- 在指标名称中使用冒号似乎与 “冒号为用户定义的记录规则保留” 相悖。
- 我们的大多数指标都遵循以单位结尾的约定,但并非所有指标都如此。
-
我们的一些指标名称以
_total结尾如果指标名称中存在
_total后缀,则会将其移除。在暴露计数器的时间序列时,会添加_total后缀。这是为了兼容 OpenMetrics 和 Prometheus 文本格式,因为 OpenMetrics 要求_total后缀。
添加更多指标¶
关于新指标的创意不乏
- 其他项目(如 TGI)的示例
- 由特定用例产生的提案,如上文的 Kubernetes 自动缩放主题
- 可能由标准化工作(如 OpenTelemetry for Gen AI 的语义约定)产生的提案。
在添加新指标的方法上,我们应该谨慎。虽然指标通常相对容易添加
- 但移除它们可能很困难——请参阅上面的弃用部分。
- 启用它们可能会产生显著的性能影响。并且指标通常用途非常有限,除非默认启用并且可以在生产环境中使用。
- 它们对项目的开发和维护有影响。随着时间的推移添加的每个指标都使这项工作更加耗时,而且也许并非所有指标都值得在维护上进行持续的投资。
跟踪 - OpenTelemetry¶
指标提供了系统性能和健康状况随时间的聚合视图。另一方面,跟踪则跟踪单个请求在不同服务和组件之间的移动。两者都属于更广泛的“可观察性”范畴。
vLLM 支持 OpenTelemetry 跟踪
- 由 拉取请求 #4687 添加,并由 拉取请求 #20372 恢复。
- 通过
--oltp-traces-endpoint和--collect-detailed-traces配置 - OpenTelemetry 博客文章
- 用户文档
- 博客文章
- IBM 产品文档
OpenTelemetry 有一个 Gen AI 工作组。
由于指标本身就是一个很大的话题,我们认为跟踪话题与指标是分开的。
OpenTelemetry 模型前向与执行时间¶
当前实现公开了以下两个指标
vllm:model_forward_time_milliseconds(Histogram) - 当此请求在批次中时,模型前向传递所花费的时间。vllm:model_execute_time_milliseconds(Histogram) - 模型执行函数所花费的时间。这包括模型前向、跨工作节点的块/同步、CPU-GPU 同步时间和采样时间。
这些指标仅在启用 OpenTelemetry 跟踪且使用 --collect-detailed-traces=all/model/worker 时启用。该选项的文档说明
收集指定模块的详细跟踪。这涉及到使用可能昂贵和/或阻塞的操作,因此可能会对性能产生影响。
这些指标由 拉取请求 #7089 添加,并在 OpenTelemetry 跟踪中显示为
-> gen_ai.latency.time_in_scheduler: Double(0.017550230026245117)
-> gen_ai.latency.time_in_model_forward: Double(3.151565277099609)
-> gen_ai.latency.time_in_model_execute: Double(3.6468167304992676)
我们已经有了 inference_time 和 decode_time 指标,所以问题在于是否有足够常见的用例需要更高分辨率的时间来证明开销是合理的。
由于我们将 OpenTelemetry 支持的问题单独处理,因此我们将这些特定指标归入该主题。


