配置 NIM#

NVIDIA NIM for VLMs 在底层使用 Docker 容器。每个 NIM 都有自己的 Docker 容器,并且有多种配置方式。以下是如何配置 NIM 容器的完整参考。

GPU 选择#

在具有一个或多个相同 GPU 的同构环境中,将 --gpus all 传递给 docker run 是可以接受的。

在具有 GPU 组合(A6000 + GeForce 显示 GPU)的异构环境中,工作负载应仅在具有计算能力的 GPU 上运行。使用以下任一方法在容器内公开特定 GPU

  •  --gpus 标志(例如:--gpus='"device=1"'

  •  环境变量 CUDA_VISIBLE_DEVICES(例如:-e CUDA_VISIBLE_DEVICES=1

要用作输入的设备 ID 列在 nvidia-smi -L 的输出中

GPU 0: Tesla H100 (UUID: GPU-b404a1a1-d532-5b5c-20bc-b34e37f3ac46)
GPU 1: NVIDIA GeForce RTX 3080 (UUID: GPU-b404a1a1-d532-5b5c-20bc-b34e37f3ac46)

有关更多说明,请参阅 NVIDIA Container Toolkit 文档

共享内存标志#

当不使用 NVLink 进行多 GPU 设置时,需要将 --shm-size=16GB 传递给 docker run。在 SXM 系统上或当使用仅使用 1 个 GPU 的配置文件时(例如,NIM_TENSOR_PARALLEL_SIZE=1),这是不必要的。

环境变量#

以下是可以传递到 NIM 中的环境变量参考(-e 添加到 docker run

ENV

必需?

默认值

注释

NGC_API_KEY

您必须将此变量设置为您的个人 NGC API 密钥的值。

NIM_CACHE_PATH

/opt/nim/.cache

容器缓存模型工件的位置(在容器中)。

NIM_DISABLE_LOG_REQUESTS

1

设置为 0 以查看请求日志。默认情况下,禁用 v1/chat/completions 的请求详细信息日志。这些日志包含请求的敏感属性,包括提示、sampling_params 和 prompt_token_ids。用户应注意,启用此参数后,这些属性将暴露于容器日志。

NIM_JSONL_LOGGING

0

设置为 1 以启用 JSON 格式的日志。默认情况下启用可读文本日志。

NIM_LOG_LEVEL

DEFAULT

NVIDIA NIM for VLMs 服务的日志级别。变量的可能值为 DEFAULT、TRACE、DEBUG、INFO、WARNING、ERROR、CRITICAL。在大多数情况下,DEBUG、INFO、WARNING、ERROR、CRITICAL 的效果在 Python 3 日志记录文档中进行了描述。TRACE 日志级别启用在 TRT-LLM 和 uvicorn 中打印用于调试目的的诊断信息。当 NIM_LOG_LEVEL 为 DEFAULT 时,将所有日志级别设置为 INFO,除了 TRT-LLM 日志级别等于 ERROR。当 NIM_LOG_LEVEL 为 CRITICAL 时,TRT-LLM 日志级别为 ERROR。

NIM_SERVER_PORT

8000

将 NIM 服务发布到容器内指定的端口。确保调整传递给 docker run 的 -p/–publish 标志的端口以反映这一点(例如:-p $NIM_SERVER_PORT:$NIM_SERVER_PORT)。此 : 的左侧是您的主机地址:端口,并且不必与 $NIM_SERVER_PORT 匹配。此 : 的右侧是容器内的端口,必须与 NIM_SERVER_PORT 匹配(如果未设置,则为 8000)。

NIM_MODEL_PROFILE

通过指定位于 /etc/nim/config/model_manifest.yaml 的清单中的配置文件 ID,覆盖 NIM 优化配置文件,该配置文件是自动选择的。如果未指定,NIM 将尝试选择与可用 GPU 兼容的最佳配置文件。可以通过在 docker run 命令末尾附加 list-model-profiles 来获得兼容配置文件的列表。使用配置文件名称 default 将选择最大兼容性的配置文件,但可能不是您硬件的最佳配置文件。

NIM_MANIFEST_ALLOW_UNSAFE

0

如果设置为 1,则启用选择未包含在原始 model_manifest.yaml 中的模型配置文件,或未检测到与已部署硬件兼容的配置文件。

NIM_SERVED_MODEL_NAME

API 中使用的模型名称。如果提供多个名称(逗号分隔),服务器将响应任何提供的名称。响应的模型字段中的模型名称将是此列表中的第一个名称。如果未指定,模型名称将从位于 /etc/nim/config/model_manifest.yaml 的清单中推断出来。请注意,此名称也将用于 Prometheus 指标的模型名称标签内容中,如果提供多个名称,则指标标签将采用第一个名称。

NIM_ENABLE_OTEL

0

将此标志设置为 1 以在 NIM 中启用 OpenTelemetry instrumentation。

OTEL_TRACES_EXPORTER

console

指定用于跟踪的 OpenTelemetry 导出器。将此标志设置为 otlp 以使用 OpenTelemetry 协议导出跟踪。将其设置为 console 以将跟踪打印到标准输出。

OTEL_METRICS_EXPORTER

console

OTEL_TRACES_EXPORTER 类似,但用于指标。

OTEL_EXPORTER_OTLP_ENDPOINT

OpenTelemetry Collector 正在侦听 OTLP 数据的端点。调整 URL 以匹配您的 OpenTelemetry Collector 的配置。

OTEL_SERVICE_NAME

设置您的服务名称,以帮助识别和分类数据。

NIM_TOKENIZER_MODE

auto

tokenizer 模式。auto 将在可用时使用快速 tokenizer。slow 将始终使用慢速 tokenizer。

NIM_ENABLE_KV_CACHE_REUSE

0

设置为 1 以启用自动前缀缓存/ KV 缓存重用。适用于大型提示频繁出现并且跨请求的 KV 缓存缓存会加速推理的用例。

OTEL_SERVICE_NAME

设置您的服务名称,以帮助识别和分类数据。

NIM_MAX_NUM_SEQS

可以并行处理的最大序列数。可以将其设置为较低的值以限制内存使用,但会牺牲性能。如果未指定,将自动从模型配置 (TRT-LLM) 或 vLLM 默认值派生

NIM_MAX_MODEL_LEN

模型上下文长度。如果未指定,将自动从模型配置派生。请注意,此设置仅对在 vLLM 后端上运行的模型有效。

NIM_KVCACHE_PERCENT

0.9

分配给 KV 缓存的可用内存百分比。可以将其设置为较低的值以限制内存使用,但会牺牲性能或丢失长上下文支持。

NIM_ENCODER_BATCHING_MS

10

视觉编码器等待其他请求到达的时间。增加批处理视觉处理的机会,但会牺牲延迟。

#

以下是容器内用于挂载本地路径的路径。

容器路径

必需?

注释

Docker 参数示例

/opt/nim/.cache(或 NIM_CACHE_PATH 如果存在)

不是必需的,但如果未挂载此卷,容器每次启动时都会全新下载模型。

这是在容器内下载模型的目录。非常重要的是,可以从容器内部访问此目录。这可以通过将选项 -u $(id -u) 添加到 docker run 命令来实现。

例如,要使用 ~/.cache/nim 作为主机目录来缓存模型,请先执行 mkdir -p ~/.cache/nim,然后再运行 docker run ... 命令。

-v ~/.cache/nim:/opt/nim/.cache -u $(id -u)

高级性能配置#

NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN#

此参数可以通过平衡文本和图像 KV 缓存之间的内存分配来最大化系统吞吐量,从而确保最大并发序列,而不会在自注意力或交叉注意力 KV 缓存中出现瓶颈。

内存分配概述

当 NIM 使用 TRTLLM 后端启动时,它会

  1. 为模型权重、激活和运行时缓冲区保留内存

  2. 将剩余内存分配给 KV 缓存

  3. 将 KV 缓存拆分为两个池,用于像 Llama 3.2 Vision 这样的编码器-解码器模型

  • 文本令牌池(自注意力)

  • 图像令牌池(交叉注意力)

拆分比例在服务器启动时确定。超出任一缓存容量的请求将排队。

示例:内存拆分比例的影响

假设

  • 每个图像对应 1k 个图像令牌

  • 可用内存允许 10k 个令牌放入 KV 缓存

  • 预期的文本序列长度为 1.5k (ISL+OSL)

  • 所有请求都包含图像

如果选择内存拆分,以便将其中的 20% 分配给图像 KV 缓存,则将有

  • 文本 KV 缓存中最多 8k 个令牌

  • 图像 KV 缓存中最多 2k 个令牌

使用该配置,服务器受到图像 KV 缓存的瓶颈限制,并且永远只能并发运行 2 个请求 (2k / 1k)。在这种情况下,超过一半的文本 KV 缓存将保持未使用状态 (5k / 8k)。

如果选择更好的拆分,例如 40%,则将有

  • 文本 KV 缓存中最多 6k 个令牌

  • 图像 KV 缓存中最多 4k 个令牌

此方案非常平衡,因为 4 个请求可以容纳并完全占用两个 KV 缓存(4 * 1k = 4k,4 * 1.5k = 6k)。由于最大并发数现在为 4 而不是 2,因此总体系统吞吐量得到提高。

实际配置

最佳拆分值取决于多个因素,例如交叉注意力层的相对数量、它们的头大小、可变大小的图像等。

为了简化配置,NIM for VLMs 提供了 NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN 参数。

例如,如果典型请求具有

  • ISL=2000

  • OSL=500

  • 最大尺寸图像(Llama 3.2 Vision 为 1120x1120)

则应设置 NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN=2500

如果只有 75% 的请求预计包含图像,则应调整该值

NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN=2500/0.75.

如果图像预计不是全尺寸,而是小一半(在 Llama 3.2 Vision 中,这对应于使用一半的图像令牌),则

NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN=2500/(0.75*0.5)

通用公式

NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN=(EXPECTED_ISL + EXPECTED_OSL) / (EXPECTED_RATIO_OF_IMAGE_REQUESTS * EXPECTED_IMAGE_SIZE_RATIO)

警告

NIM_ENCODER_KV_RATIO_TARGET_SEQ_LEN 设置得太低可能会阻止文本 KV 缓存处理最大支持的序列长度(例如,Llama 3.2 Vision 为 128k)。