文章目录
- 获取TensorRT-LLM代码:
- 构建docker镜像并安装TensorRT-LLM:
- 运行docker镜像:
- 安装依赖
- 魔改下部分package代码:
- 量化:
- 构建图:
- 全局参数
- 插件配置
- 常用配置参数
- 测试推理是否可以
- 代码推理
- CLI推理
- 性能测试
- 小结
- 验证是否严重退化
- 使用NVIDIA Triton部署在线推理服务器
- 代码弄下来
- 编译镜像
- 启动容器
- 安装依赖
- 量化
- 构建trt engines图
- Triton 模板
- 说明
- 实操
- 发起Triton服务
- 请求服务试试
- 示例说明
- 模型分析器
- 关闭Triton服务
- metric
- 重看Triton服务
官方文档:
https://nvidia.github.io/TensorRT-LLM/quick-start-guide.html#launch-the-docker
参考资料源:
https://swanhub.co/ZhipuAI/ChatGLM3/blob/main/tensorrt_llm_demo/README.md
https://github.com/THUDM/GLM-4/issues/132
TensorRT-LLM官方目前说在v0.12.0版本才会支持GLM-4-9B Chat ,下面以v0.10.0的魔改来做GLM-4-9B Chat的量化部署。
本文目标就是加速GLM-4-9B Chat,看看能多快。A100卡。
获取TensorRT-LLM代码:
# TensorRT-LLM 代码需要使用 git-lfs 拉取
apt-get update && apt-get -y install git git-lfsgit clone https://github.com/NVIDIA/TensorRT-LLM.git
cd TensorRT-LLM# 本流程将使用 v0.10.0 Release 版本
git checkout tags/v0.10.0 -b release/0.10.0
git submodule update --init --recursive
git lfs install
git lfs pull
构建docker镜像并安装TensorRT-LLM:
这是编译,要魔法。可以跳过这一条看下一节“运行docker镜像”。
make -C docker release_build
运行docker镜像:
这是有源码的简易启动方式:
make -C docker release_run
我编译好上传了这个镜像,所以我这么启动:
docker run -it --ipc=host --ulimit memlock=-1 --ulimit stack=67108864 \--gpus=all \--volume /ssd/xiedong/glm-4-9b-xd:/ssd/xiedong/glm-4-9b-xd \--env "CCACHE_DIR=/code/tensorrt_llm/cpp/.ccache" \--env "CCACHE_BASEDIR=/code/tensorrt_llm" \--workdir /app/tensorrt_llm \--hostname euler-MS-7D30-release \--tmpfs /tmp:exec \kevinchina/deeplearning:tensorrt_llm
安装依赖
cd /ssd/xiedong/glm-4-9b-xd/TensorRT-LLM/examples/chatglm
pip install -r requirements.txt
pip install tiktoken -i https://pypi.tuna.tsinghua.edu.cn/simple
魔改下部分package代码:
vim /usr/local/lib/python3.10/dist-packages/modelopt/torch/export/model_config_export.py
export_tensorrt_llm_checkpoint
model=model -> model=model.cpu() 24G显存是真的会爆的
vim /usr/local/lib/python3.10/dist-packages/tensorrt_llm/models/chatglm/model.py
ChatGLMForCausalLM > check_config
config.set_if_not_exist(‘chatglm_version’, ‘chatglm3’) -> config.chatglm_version = “chatglm3” 强制套用chatglm3相关代码
量化:
cd /ssd/xiedong/glm-4-9b-xd/TensorRT-LLMCUDA_VISIBLE_DEVICES=2 python examples/quantization/quantize.py --model_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat --dtype float16 --qformat int4_awq --output_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq --batch_size 8
让我们逐一详细介绍quantize.py中的参数,包括它们的默认值、含义以及所有可能的值。
-
--model_dir
:- 默认值:
None
- 含义: 指定HuggingFace模型所在的目录。
- 所有可能的值: 任意有效的文件路径。
- 默认值:
-
--nemo_ckpt_path
:- 默认值:
None
- 含义: 指定NeMo模型检查点文件所在的路径。
- 所有可能的值: 任意有效的文件路径。
- 默认值:
-
--decoder_type
:- 默认值:
'gptnext'
- 含义: 解码器类型,仅对NeMo检查点有效。
- 所有可能的值:
'gptnext'
,'llama'
- 默认值:
-
--device
:- 默认值:
'cuda'
- 含义: 运行校准的设备,仅对HuggingFace模型有效。
- 所有可能的值:
'cuda'
,'cpu'
- 默认值:
-
--calib_dataset
:- 默认值:
'cnn_dailymail'
- 含义: 用于校准的HuggingFace数据集名称或本地数据集目录。
- 所有可能的值: 任意有效的HuggingFace数据集名称或本地路径。
- 默认值:
-
--calib_tp_size
:- 默认值:
1
- 含义: 校准的张量并行大小,仅对NeMo检查点有效。
- 所有可能的值: 正整数。
- 默认值:
-
--calib_pp_size
:- 默认值:
1
- 含义: 校准的流水线并行大小,仅对NeMo检查点有效。
- 所有可能的值: 正整数。
- 默认值:
-
--dtype
:- 默认值:
'float16'
- 含义: 模型数据类型。
- 所有可能的值:
'float16'
,'float32'
, 其他有效的浮点类型。
- 默认值:
-
--qformat
:- 默认值:
'full_prec'
- 含义: 量化格式。
- 所有可能的值:
'fp8'
,'int8_sq'
,'int4_awq'
,'w4a8_awq'
,'int8_wo'
,'int4_wo'
,'full_prec'
- 默认值:
量化格式 | 描述 | 优势 | 劣势 | 常用场景 | 选择建议 |
---|---|---|---|---|---|
fp8 | 8位浮点数格式 | 动态范围大,精度较高 | 复杂度高,硬件支持有限 | 大规模语言模型(LLMs)、图像处理任务 | 平衡精度和计算效率,适用于需要高精度和大范围的数据 |
int8_sq | 8位整数,平方量化(SmoothQuant) | 推理速度快,计算效率高 | 精度损失较大 | 实时推理任务 | 适用于需要快速推理且对精度要求不高的场景 |
int4_awq | 4位整数,权重近似量化(AWQ) | 存储和计算资源需求低 | 精度损失明显 | 边缘设备 | 适用于极端资源受限的环境 |
w4a8_awq | 权重4位整数,激活8位整数,AWQ方法 | 平衡存储效率和推理精度 | 实现复杂,硬件支持要求高 | 存储受限但需要高精度推理的场景 | 适用于需要高精度推理且存储资源有限的场景 |
int8_wo | 8位整数量化,仅权重 | 存储需求低,计算效率高 | 精度损失较大 | 存储受限但计算资源较充足的环境 | 适用于权重较平滑且不易受量化影响的模型 |
int4_wo | 4位整数量化,仅权重 | 存储和计算资源需求极低 | 精度损失极大 | 极端受限的嵌入式设备或边缘计算 | 适用于非常受限的嵌入式设备或边缘计算场景 |
full_prec | 全精度格式,不进行量化 | 保持原始精度,无精度损失 | 存储和计算资源需求大 | 模型训练阶段或高精度需求的推理任务 | 适用于需要最高精度且不受资源限制的场景 |
-
--seed
:- 默认值:
1234
- 含义: 用于生成随机数的种子值,将用于调用
random.seed(value)
和numpy.random.seed(value)
。 - 所有可能的值: 任意整数。
- 默认值:
-
--tokenizer_max_seq_length
:- 默认值:
2048
- 含义: 初始化分词器的最大序列长度。
- 所有可能的值: 正整数。
- 默认值:
-
--batch_size
:- 默认值:
1
- 含义: 校准的批次大小。
- 所有可能的值: 正整数。
- 默认值:
-
--calib_size
:- 默认值:
512
- 含义: 用于校准的样本数量。
- 所有可能的值: 正整数。
- 默认值:
-
--calib_max_seq_length
:- 默认值:
512
- 含义: 校准的最大序列长度。
- 所有可能的值: 正整数。
- 默认值:
-
--output_dir
:- 默认值:
'exported_model'
- 含义: 导出模型的目录。
- 所有可能的值: 任意有效的文件路径。
- 默认值:
-
--tp_size
:- 默认值:
1
- 含义: 张量并行大小。
- 所有可能的值: 正整数。
- 默认值:
-
--pp_size
:- 默认值:
1
- 含义: 流水线并行大小。
- 所有可能的值: 正整数。
- 默认值:
-
--awq_block_size
:- 默认值:
128
- 含义: AWQ(Approximate Weight Quantization)块大小。
- 所有可能的值: 正整数。
- 默认值:
-
--kv_cache_dtype
:- 默认值:
None
- 含义: KV缓存的数据类型。
- 所有可能的值:
'int8'
,'fp8'
,None
- 默认值:
-
--num_medusa_heads
:- 默认值:
4
- 含义: Medusa头的数量。
- 所有可能的值: 正整数。
- 默认值:
-
--num_medusa_layers
:- 默认值:
1
- 含义: Medusa层的数量。
- 所有可能的值: 正整数。
- 默认值:
-
--max_draft_len
:- 默认值:
63
- 含义: 最大草稿长度。
- 所有可能的值: 正整数。
- 默认值:
-
--medusa_hidden_act
:- 默认值:
'silu'
- 含义: Medusa隐藏层激活函数。
- 所有可能的值:
'relu'
,'tanh'
,'gelu'
,'silu'
等有效的激活函数。
- 默认值:
-
--medusa_model_dir
:- 默认值:
None
- 含义: Medusa模型所在的目录。
- 所有可能的值: 任意有效的文件路径。
- 默认值:
-
--quant_medusa_head
:- 默认值:
False
- 含义: 是否对Medusa头的权重进行量化。
- 所有可能的值:
True
,False
- 默认值:
这些参数用于配置模型量化和导出的各种细节,确保在不同的硬件和数据集上都能进行有效的校准和导出。通过调整这些参数,可以定制化模型的量化流程以满足特定需求。
量化完成:
构建图:
cd /ssd/xiedong/glm-4-9b-xd/TensorRT-LLMCUDA_VISIBLE_DEVICES=2 trtllm-build --checkpoint_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq --gemm_plugin float16 --output_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines
构建完成:
下面是对trtllm-build参数的详细解释:
全局参数
-h, --help
: 显示帮助信息并退出。--checkpoint_dir CHECKPOINT_DIR
: 指定检查点目录。--model_config MODEL_CONFIG
: 模型配置文件路径。--build_config BUILD_CONFIG
: 构建配置文件路径。--model_cls_file MODEL_CLS_FILE
: 模型类文件路径。--model_cls_name MODEL_CLS_NAME
: 模型类名称。--input_timing_cache INPUT_TIMING_CACHE
: 读取时间缓存文件的路径,如果文件不存在将被忽略(默认值:None)。--output_timing_cache OUTPUT_TIMING_CACHE
: 写入时间缓存文件的路径(默认值:model.cache)。--log_level LOG_LEVEL
: 日志级别。--profiling_verbosity {layer_names_only,detailed,none}
: 设置生成的TRT引擎的分析详细程度。设置为detailed可以检查策略选择和内核参数。(默认值:layer_names_only)--enable_debug_output
: 启用调试输出。--output_dir OUTPUT_DIR
: 保存序列化引擎文件和模型配置的路径(默认值:engine_outputs)。--workers WORKERS
: 并行构建的工作线程数(默认值:1)。--max_batch_size MAX_BATCH_SIZE
: 引擎可以处理的最大请求数量。(默认值:256)--max_input_len MAX_INPUT_LEN
: 单个请求的最大输入长度。(默认值:1024)--max_seq_len MAX_SEQ_LEN, --max_decoder_seq_len MAX_SEQ_LEN
: 单个请求的最大总长度,包括提示和输出。如果未指定,将尝试从模型配置中推断。(默认值:None)--max_beam_width MAX_BEAM_WIDTH
: 最大的束宽。--max_num_tokens MAX_NUM_TOKENS
: 在每个批次中移除填充后的批处理输入标记的最大数量(触发--remove_input_padding
)。(默认值:8192)--opt_num_tokens OPT_NUM_TOKENS
: 默认等于max_batch_size*max_beam_width,设置该值尽可能接近工作负载的实际标记数量。注意此参数可能在未来被移除。(默认值:None)--tp_size TP_SIZE
: 并行的张量大小。--pp_size PP_SIZE
: 并行的流水线大小。--max_prompt_embedding_table_size MAX_PROMPT_EMBEDDING_TABLE_SIZE, --max_multimodal_len MAX_PROMPT_EMBEDDING_TABLE_SIZE
: 设置为大于0的值以启用提示调整或多模态输入支持。(默认值:0)--use_fused_mlp
: 在GatedMLP中启用水平融合,减少层输入流量并可能提高性能。对于FP8 PTQ,缺点是由于丢弃了一个量化缩放因子,精度略有下降。(仅供参考的示例:0.45734 vs 0.45755用于LLaMA-v2 7B使用modelopt/examples/hf/instruct_eval/mmlu.py
)。(默认值:False)--gather_all_token_logits
: 启用gather_context_logits和gather_generation_logits。(默认值:False)--gather_context_logits
: 收集上下文logits。(默认值:False)--gather_generation_logits
: 收集生成logits。(默认值:False)--builder_opt BUILDER_OPT
: 构建器选项。--builder_force_num_profiles BUILDER_FORCE_NUM_PROFILES
: 强制构建的配置文件数量。--logits_dtype {float16,float32}
: logits的数据类型。--weight_sparsity
: 权重稀疏性。--max_draft_len MAX_DRAFT_LEN
: 猜测解码目标模型的最大草稿标记长度。(默认值:0)--lora_dir LORA_DIR [LORA_DIR ...]
: LoRA权重的目录。如果提供多个目录,将使用第一个目录的配置。(默认值:None)--lora_ckpt_source {hf,nemo}
: LoRA检查点的来源。(默认值:hf)--lora_target_modules {attn_qkv,attn_q,attn_k,attn_v,attn_dense,mlp_h_to_4h,mlp_4h_to_h,mlp_gate,cross_attn_qkv,cross_attn_q,cross_attn_k,cross_attn_v,cross_attn_dense,moe_h_to_4h,moe_4h_to_h,moe_gate,moe_router} [{attn_qkv,attn_q,attn_k,attn_v,attn_dense,mlp_h_to_4h,mlp_4h_to_h,mlp_gate,cross_attn_qkv,cross_attn_q,cross_attn_k,cross_attn_v,cross_attn_dense,moe_h_to_4h,moe_4h_to_h,moe_gate,moe_router} ...]
: 在哪些模块中添加LoRA。仅在启用use_lora_plugin时激活。(默认值:None)--max_lora_rank MAX_LORA_RANK
: 各个LoRA模块的最大LoRA秩。用于计算LoRA插件的工作空间大小。(默认值:64)--auto_parallel AUTO_PARALLEL
: 自动并行的MPI世界大小。(默认值:1)--gpus_per_node GPUS_PER_NODE
: 多节点设置中每个节点的GPU数量。这是一个集群规格,可以大于/小于世界大小(默认值:8)--cluster_key {A100-SXM-80GB,A100-SXM-40GB,A100-PCIe-80GB,A100-PCIe-40GB,H100-SXM,H100-PCIe,H20,V100-PCIe-16GB,V100-PCIe-32GB,V100-SXM-16GB,V100-SXM-32GB,V100S-PCIe,A40,A30,A10,A10G,L40S,L40,L20,L4,L2}
: 目标GPU类型的唯一名称。如果未指定,将从当前GPU类型推断。(默认值:None)--strip_plan
: 是否从最终的TRT引擎中剥离权重,假设重新拟合的权重将与构建时提供的权重相同。(默认值:False)--max_encoder_input_len MAX_ENCODER_INPUT_LEN
: 使用编码器-解码器模型时指定最大编码器输入长度。将max_input_len设置为1以从decoder_start_token_id长度1开始生成。(默认值:1024)--visualize_network
: 在引擎构建前将TRT网络导出为ONNX以进行调试。(默认值:False)--dry_run
: 在不实际构建引擎的情况下运行构建过程以进行调试。(默认值:False)--speculative_decoding_mode {draft_tokens_external,lookahead_decoding,medusa,explicit_draft_tokens}
: 猜测解码模式。(默认值:None)--weight_streaming
: 指定是否将权重卸载到CPU并在运行时流式加载。(默认值:False)
插件配置
--bert_attention_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用BERT注意力插件及其数据类型。(默认值:auto)--gpt_attention_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用GPT注意力插件及其数据类型。(默认值:auto)--gemm_plugin {auto,float16,float32,bfloat16,int32,fp8,disable}
: 启用/禁用GEMM插件及其数据类型。(默认值:disable)GEMM插件用于优化矩阵乘法操作,特别是在深度学习模型中,这些操作是计算密集型的核心部分。通过启用GEMM插件,可以利用硬件加速器和专门优化的算法,提升矩阵乘法的性能。--gemm_swiglu_plugin {fp8,disable}
: 启用/禁用GEMM SwiGLU插件及其数据类型。(默认值:disable)--fp8_rowwise_gemm_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用FP8逐行GEMM插件及其数据类型。(默认值:disable)--nccl_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用NCCL插件及其数据类型。(默认值:auto)--lookup_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用查找插件及其数据类型。(默认值:disable)--lora_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用LoRA插件及其数据类型。(默认值:disable)--moe_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用MoE插件及其数据类型。(默认值:auto)--mamba_conv1d_plugin {auto,float16,float32,bfloat16,int32,disable}
: 启用/禁用Mamba Conv1D插件及其数据类型。(默认
值:auto)
--context_fmha {enable,disable}
: 启用/禁用上下文FMHA。(默认值:enable)--context_fmha_fp32_acc {enable,disable}
: 启用/禁用上下文FMHA FP32精度。(默认值:disable)--paged_kv_cache {enable,disable}
: 启用/禁用分页键值缓存。(默认值:enable)--remove_input_padding {enable,disable}
: 启用/禁用移除输入填充。(默认值:enable)--reduce_fusion {enable,disable}
: 启用/禁用融合减少。(默认值:disable)--enable_xqa {enable,disable}
: 启用/禁用XQA。(默认值:enable)--tokens_per_block TOKENS_PER_BLOCK
: 每个块的标记数。(默认值:64)--use_paged_context_fmha {enable,disable}
: 启用/禁用使用分页上下文FMHA。(默认值:disable)--use_fp8_context_fmha {enable,disable}
: 启用/禁用使用FP8上下文FMHA。(默认值:disable)--multiple_profiles {enable,disable}
: 启用/禁用多个配置文件。(默认值:disable)--paged_state {enable,disable}
: 启用/禁用分页状态。(默认值:enable)--streamingllm {enable,disable}
: 启用/禁用流式LLM。(默认值:disable)
这些参数主要用于配置和优化深度学习模型的训练和推理过程。通过合理设置这些参数,可以提高模型的性能和效率。
trtllm-build
是一个用于构建 TensorRT 引擎的命令行工具,常用于大规模语言模型 (LLM) 的优化和部署。为了获得最佳性能,通常会使用多种配置选项来调整构建过程。以下是一些常见的配置及其作用:
常用配置参数
-
数据类型和插件配置
--gemm_plugin float16
: 启用 GEMM 插件并使用 float16 数据类型,可以显著提高矩阵乘法的计算效率,减少内存占用【13†source】。--bert_attention_plugin
和--gpt_attention_plugin
: 控制是否启用 BERT 和 GPT 的注意力插件,选择相应的数据类型来优化注意力机制【14†source】。--use_fused_mlp
: 启用 Gated-MLP 的水平融合,合并多个矩阵乘法操作,以提高性能【14†source】。
-
并行化和缓存配置
--tp_size
和--pp_size
: 分别指定张量并行和流水线并行的大小,用于多 GPU 环境下的并行计算【15†source】。--paged_kv_cache enable
: 启用分页键值缓存,提高缓存管理效率,增加批处理大小并提高效率【14†source】。
-
优化和调试配置
--profiling_verbosity {layer_names_only, detailed, none}
: 设置生成的 TensorRT 引擎的分析详细程度,可以帮助调试和优化【15†source】。--enable_debug_output
: 启用调试输出,有助于在构建过程中检测问题【13†source】。--dry_run
和--visualize_network
: 在不实际构建引擎的情况下运行构建过程,并在构建前导出 TensorRT 网络以进行调试【14†source】【15†source】。
-
输入输出配置
--max_input_len
和--max_output_len
: 设置输入和输出的最大序列长度,确保模型处理能力符合预期【15†source】。--max_batch_size
: 设置模型可以处理的最大批处理大小,有助于提高推理效率【15†source】。
-
量化配置
--weight_sparsity
: 启用权重稀疏性,减少模型的内存占用,提高推理速度【13†source】。--quantization.quant_algo
和--quantization.kv_cache_quant_algo
: 设置量化算法,用于优化模型的存储和计算【16†source】。
这些配置可以根据模型的具体需求和硬件环境进行调整,以最大化性能和效率。对于具体的模型和场景,可能需要根据实际情况进行一些实验和调整,确保达到最佳效果。
更多详细信息和示例配置可以参考 TensorRT-LLM 文档【12†source】【13†source】【14†source】【15†source】【16†source】。
测试推理是否可以
代码推理
cd /ssd/xiedong/glm-4-9b-xd
vim testglm-4-9b-chat-int4_awq-engines.py
from transformers import AutoTokenizer
import torchtokenizer = AutoTokenizer.from_pretrained("/ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat", trust_remote_code=True)import tensorrt_llmrunner = tensorrt_llm.runtime.ModelRunnerCpp.from_dir("/ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines")history = [{'role': 'system', 'content': '你是一个Python程序员。'},# 可选,few shots
]conversation = history.copy()
conversation.append({"role": "user", "content": "请写一个用Python实现的程序,功能是将一个字符串中的所有字母转换为大写字母。"})inputs = tokenizer.apply_chat_template(conversation,add_generation_prompt=True,tokenize=True,return_tensors="pt",return_dict=True)inputs = inputs.to("cuda")with torch.no_grad():outputs = runner.generate([inputs["input_ids"][0]],max_new_tokens=1280,end_id=151336, # 参考上面的讨论pad_id=151329,temperature=0,top_p=0,num_beams=1,output_sequence_lengths=True,return_dict=True,exclude_input_in_output=True)print(tokenizer.decode(outputs["output_ids"][0, 0][inputs["input_ids"].shape[1]:outputs["sequence_lengths"][0]]))
执行代码:
CUDA_VISIBLE_DEVICES=2 python testglm-4-9b-chat-int4_awq-engines.py
可以得到结果:
CLI推理
单机单卡的推理示例:
cd /ssd/xiedong/glm-4-9b-xdCUDA_VISIBLE_DEVICES=2 python3 /ssd/xiedong/glm-4-9b-xd/TensorRT-LLM/examples/run.py --input_text "What's new between ChatGLM3-6B and ChatGLM2-6B?" \--max_output_len 50 \--tokenizer_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat \--engine_dir "/ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines"
性能测试
没空看代码,先放着:
https://github.com/NVIDIA/TensorRT-LLM/tree/main/benchmarks/python
小结
将自己用的TensorRT-LLM/文件夹cp一份放到了/workspace.
commit此容器并push:
docker commit b42769f7ed16 kevinchina/deeplearning:tensorrt_llm-v0.10.0
验证是否严重退化
参考了这里的文章:https://www.chenshaowen.com/blog/using-triton-server-and-tensorrt-llm-under-container.html
在精度损失可接受的范围内,模型的推理优化才有意义。TensorRT-LLM 项目提供的 summarize.py 可以跑一些测试,给模型打分,rouge1、rouge2 和 rougeLsum 是用于评价文本生成质量的指标,可以用于评估模型推理质量。
pip install datasets nltk rouge_score -i https://pypi.tuna.tsinghua.edu.cn/simple
test_hf 得到的是原始模型的指标,执行:
cd /ssd/xiedong/glm-4-9b-xdCUDA_VISIBLE_DEVICES=2 python3 /ssd/xiedong/glm-4-9b-xd/TensorRT-LLM/examples/summarize.py --test_hf \--hf_model_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat \--data_type fp16 \--engine_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines
获得TensorRT模型的指标,执行:
cd /ssd/xiedong/glm-4-9b-xdCUDA_VISIBLE_DEVICES=2 python3 /ssd/xiedong/glm-4-9b-xd/TensorRT-LLM/examples/summarize.py --test_trt_llm \--hf_model_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat \--data_type fp16 \--engine_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines
模型不支持,估计TensorRT-LLM后面版本才行。
使用NVIDIA Triton部署在线推理服务器
下图显示了 Triton 推理服务器的高级架构。模型存储库是一个基于文件系统的存储库,其中包含 Triton 将用于推理的模型。推理请求通过HTTP/REST 或 GRPC或C API到达服务器,然后路由到适当的每个模型调度程序。Triton 实现了多种调度和批处理算法,可以根据每个模型进行配置。每个模型的调度程序可以选择执行推理请求的批处理,然后将请求传递给与 模型类型相对应的后端 。后端使用批处理请求中提供的输入执行推理以生成请求的输出。然后返回输出。
从23版本后,Triton的docker容器里就有 TensorRT-LLM了,不用自己装了,很nice。也就是上面的内容都可以作废了,重新开始。
部署大语言模型(LLM)在生产环境中,你可以使用Triton Inference Server和TensorRT-LLM后端,以利用TensorRT-LLM C++运行时进行快速推理执行,并包括如飞行批处理和分页KV缓存等优化。
以下是具体步骤:
拉取一个Triton镜像下来,官网有很多Triton镜像:
https://catalog.ngc.nvidia.com/orgs/nvidia/containers/tritonserver/tags
看这里资料:
https://github.com/triton-inference-server/tensorrtllm_backend
https://github.com/NVIDIA/TensorRT-LLM/blob/main/examples/gpt/README.md
代码弄下来
不考虑tags,感觉是代码越新越好。
弄好仓库:
cd /ssd/xiedong/glm-4-9b-xd
git clone https://github.com/triton-inference-server/tensorrtllm_backend.git
cd /ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend
git submodule update --init --recursive
git lfs install
git lfs pull
编译镜像
自己编译的镜像更好,比官网出的版本高,不容易有bug。编译好镜像后,就同时有Triton和之前的tensorRTLLM在。
用仓库编译出镜像,要魔法,不然会失败:
# Update the submodules
cd tensorrtllm_backend
git lfs install
git submodule update --init --recursive# Use the Dockerfile to build the backend in a container
# For x86_64 正常机器都是这个架构
DOCKER_BUILDKIT=1 docker build -t triton_trt_llm -f dockerfile/Dockerfile.trt_llm_backend .
# For aarch64 这个架构不常用
DOCKER_BUILDKIT=1 docker build -t triton_trt_llm --build-arg TORCH_INSTALL_TYPE="src_non_cxx11_abi" -f dockerfile/Dockerfile.trt_llm_backend .
启动容器
启动容器,把宿主机有模型和代码的路径挂载进去。
docker run -it --net host --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus '"device=2,3"' -v /ssd/xiedong/glm-4-9b-xd:/ssd/xiedong/glm-4-9b-xd nvcr.io/nvidia/tritonserver:23.10-trtllm-python-py3 bash# 自己的机器
docker run -it --net host --shm-size=2g --ulimit memlock=-1 --ulimit stack=67108864 --gpus '"device=0"' -v /data/xiedong/glm4:/data/xiedong/glm4 triton_trt_llm:latest bash
安装依赖
每个项目的依赖不同,这里要安装chatglm的requirements.txt依赖。
# 这个tiktoken 包要装上
pip install tiktoken -i https://pypi.tuna.tsinghua.edu.cn/simple# 自己的机器,安装chatglm的依赖
cd /data/xiedong/glm4/tensorrtllm_backend/tensorrt_llm/examples/chatglm
pip install tiktoken -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install -r requirements.txt
为了适应chatglm-4的代码,要魔改下部分package代码:
vim /usr/local/lib/python3.10/dist-packages/modelopt/torch/export/model_config_export.py
export_tensorrt_llm_checkpoint
model=model -> model=model.cpu() 24G显存是真的会爆的
vim /usr/local/lib/python3.10/dist-packages/tensorrt_llm/models/chatglm/model.py
ChatGLMForCausalLM > check_config
config.set_if_not_exist(‘chatglm_version’, ‘chatglm3’) -> config.chatglm_version = “chatglm3” 强制套用chatglm3相关代码
量化
这里主要是将hf模型转为llm checkpoints模型,也可以直接用转换脚本,我这里直接调用quantize.py去量化并得到llm checkpoints模型。
cd /ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend/
CUDA_VISIBLE_DEVICES=0 python tensorrt_llm/examples/quantization/quantize.py --model_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat --dtype float16 --qformat int4_awq --output_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-new --batch_size 8 # 自己机器
cd /data/xiedong/glm4/tensorrtllm_backend
CUDA_VISIBLE_DEVICES=0 python tensorrt_llm/examples/quantization/quantize.py --model_dir /data/xiedong/glm4/glm-4-9b-chat --dtype float16 --qformat int4_awq --output_dir /data/xiedong/glm4/glm-4-9b-chat-awq-new --batch_size 8
官网会用convert_checkpoint.py干这些事情,不需要量化可以看convert_checkpoint.py这个脚本如何做:
# Convert weights from HF Tranformers to TensorRT-LLM checkpoint
python3 convert_checkpoint.py --model_dir gpt2 \--dtype float16 \--tp_size 4 \--output_dir ./c-model/gpt2/fp16/4-gpu
构建trt engines图
这里要将llm checkpoints模型进一步转为trt engines图,这个trt engines图就是可以被Triton server加载的模型图。
cd /ssd/xiedong/glm-4-9b-xd/TensorRT-LLM
CUDA_VISIBLE_DEVICES=2 trtllm-build --checkpoint_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq --gemm_plugin float16 --output_dir /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines# 自己机器
cd /data/xiedong/glm4/tensorrtllm_backend
CUDA_VISIBLE_DEVICES=0 trtllm-build --checkpoint_dir /data/xiedong/glm4/glm-4-9b-chat-awq-new --gemm_plugin float16 --output_dir /data/xiedong/glm4/glm-4-9b-chat-awq-new-engines
Triton 模板
说明
Triton 模板是会包含这些子文件夹,每个功能都不一样:
-
预处理模型 (preprocessing)
功能: 该模型用于将文本提示(prompts)转换为输入标识符(input_ids)。
输入: 字符串形式的文本提示。
输出: 整数列表形式的输入标识符。
用途: 主要用于将自然语言输入转换为模型可以理解和处理的格式。这是深度学习模型推理的第一步。
-
TensorRT LLM 模型 (tensorrt_llm)
功能: 该模型是一个 TensorRT-LLM 模型的包装器,用于推理。
输入: 输入规范可以在这里找到(假设是指某个特定文档或 API 说明)。
输出: 模型推理的结果,通常是标识符的形式。
用途: 用于实际的模型推理步骤,接收经过预处理的输入并生成推理结果。
-
后处理模型 (postprocessing)
功能: 该模型用于将输出标识符(output_ids)转换为输出字符串。
输入: 整数列表形式的输出标识符。
输出: 字符串形式的输出文本。
用途: 将模型的推理结果转换为可读的自然语言文本,这是推理流程的最后一步。
-
集成模型 (ensemble)
功能: 该模型用于将预处理、TensorRT LLM 和后处理模型链式连接起来。
用途: 提供一个方便的接口,以串联执行预处理、推理和后处理的所有步骤,实现从文本提示到最终输出的完整流程。
-
TensorRT LLM BLS 模型 (tensorrt_llm_bls)
功能: 同样用于将预处理、TensorRT LLM 和后处理模型链式连接起来。
区别: 尽管其功能与集成模型(ensemble)相似,但可能包含一些特定的优化或定制设置,以满足不同的性能需求或使用场景。
Triton 的集成功能支持许多用例,其中多个模型组成一个管道(或更一般地说是 DAG,有向无环图)。但是,还有许多其他用例不受支持,因为作为模型管道的一部分,它们需要循环、条件(if-then-else)、数据依赖控制流和其他自定义逻辑与模型执行混合。我们将这种自定义逻辑和模型执行的组合称为业务逻辑脚本 (BLS)。
假设我们有一个文本提示 "Hello, how are you?"
,整个推理流程如下:
-
预处理:
prompt = "Hello, how are you?" input_ids = preprocessing_model.tokenize(prompt)
-
TensorRT LLM 推理:
output_ids = tensorrt_llm_model.infer(input_ids)
-
后处理:
output_text = postprocessing_model.detokenize(output_ids)
-
集成模型:
output_text = ensemble_model.process(prompt)
在使用 BLS 模型替代集成模型时,应将模型实例数量设置为 TRT 引擎支持的最大批处理大小,以允许并发请求执行。这可以通过修改 BLS 模型 config.pbtxt
文件中 instance_group
部分的 count
值来实现。
BLS 模型有一个可选参数 accumulate_tokens
,可在流模式下使用,以使用所有累积的 tokens 调用后处理模型,而不仅仅是一个 token。某些分词器可能需要此功能。
BLS 模型支持推测解码。目标和草稿的 Triton 模型通过参数 tensorrt_llm_model_name
和 tensorrt_llm_draft_model_name
设置。通过在请求中设置 num_draft_tokens
来执行推测解码。可以通过设置 use_draft_logits
来使用 logits 比较进行推测解码。请注意,在使用推测解码时,不支持 return_generation_logits
和 return_context_logits
。还需注意,目前推测解码不支持批量大小大于 1 的请求。
阅读这里了解更多:https://github.com/triton-inference-server/server/blob/main/docs/user_guide/architecture.md#ensemble-models
实操
创建Triton tensorrtllm_backend 的模板工程:
cd /ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend
mkdir triton_model_repo
# Copy the example models to the model repository
cp -r all_models/inflight_batcher_llm/* triton_model_repo/
# Copy the TRT engine to triton_model_repo/tensorrt_llm/1/
cp /ssd/xiedong/glm-4-9b-xd/glm-4-9b-chat-int4_awq-engines/* triton_model_repo/tensorrt_llm/1# 自己机器
cd /data/xiedong/glm4/tensorrtllm_backend
mkdir triton_model_repo
cp -r all_models/inflight_batcher_llm/* triton_model_repo/
cp /data/xiedong/glm4/glm-4-9b-chat-awq-new-engines/* triton_model_repo/tensorrt_llm/1
triton_model_repo中就是一个工程模板了,模板里各个子文件夹都是配置,需要改,这里说了怎么改:https://github.com/triton-inference-server/tensorrtllm_backend。按文档里说的改一下。
改半天还是错了,这个指令看是哪个叼毛还报错:
find triton_model_repo/ -type f -name "*txt" -exec grep -l 'batch_scheduler_policy' {} +
我写了个python代码,来一键替换配置文件里的字符串,更改src 为模板路径,更改replace_d字典的替换关系。
import osdef listPathAllfiles(dirname):result = []for maindir, subdir, file_name_list in os.walk(dirname):for filename in file_name_list:apath = os.path.join(maindir, filename)result.append(apath)return resultsrc = r"/data/xiedong/glm4/tensorrtllm_backend/triton_model_repo"
files = listPathAllfiles(src)# 过滤只要pbtxt结尾的文件
files = [file for file in files if file.endswith(".pbtxt")]
print("有的pbtxt文件:")
for file in files:print(file)# 字符串替换的字典
replace_d = {"${triton_max_batch_size}": 32,"${postprocessing_instance_count}": 8,"${tokenizer_dir}": "/data/xiedong/glm4/glm-4-9b-chat","${decoupled_mode}": "true","${max_queue_delay_microseconds}": 5000000,"${triton_backend}": "tensorrtllm",# gpt_model_path"${engine_dir}": "/data/xiedong/glm4/tensorrtllm_backend/triton_model_repo/tensorrt_llm/1","${batch_scheduler_policy}": "max_utilization","${preprocessing_instance_count}": 8,# gpt_model_type"${batching_strategy}": "inflight_fused_batching","${bls_instance_count}": 1,#"${max_tokens_in_paged_kv_cache}": 1048577,"beam_width": "fuck is where?","maxTokensInPagedKvCache": "fuck is where?","tokensPerBlock": "fuck is where?","maxBlocksPerSeq": "fuck is where?","max_tokens_in_paged_kv_cache": "fuck is where?",
}
print("开始修改:")
# 读取文件内容,替换字符串,写入原文件
for file in files:with open(file, "r") as f:content = f.read()for k, v in replace_d.items():if v == "fuck is where?":if str(k) in content:print(f"ERROR fuck is where?: {k},{file}")else:if str(k) in content:content = content.replace(str(k), str(v))print(f"INFO tihuan: {file},{k},{v}")with open(file, "w") as f:f.write(content)print(f"{file} done!")
发起Triton服务
发起Triton服务:
cd /ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend
# --world_size is the number of GPUs you want to use for serving
python3 /ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend/scripts/launch_triton_server.py --world_size=1 --model_repo=/ssd/xiedong/glm-4-9b-xd/tensorrtllm_backend/triton_model_repo# 自己机器
cd /data/xiedong/glm4/
python3 /data/xiedong/glm4/tensorrtllm_backend/scripts/launch_triton_server.py --world_size=1 --model_repo=/data/xiedong/glm4/tensorrtllm_backend/triton_model_repo
好像是可以了:
# 自己机器
docker commit 883bd4b12b5b kevinchina/deeplearning:triton_trt_llm-successv1
docker run -it -p 7866:8000 -p 7867:8001 -p 7868:8002 --shm-size=8g --ulimit memlock=-1 --ulimit stack=67108864 --gpus '"device=0"' -v /data/xiedong/glm4:/data/xiedong/glm4 kevinchina/deeplearning:triton_trt_llm-successv1 bash
cd /data/xiedong/glm4/
python3 /data/xiedong/glm4/tensorrtllm_backend/scripts/launch_triton_server.py --world_size=1 --model_repo=/data/xiedong/glm4/tensorrtllm_backend/triton_model_repo
开启成功:
请求服务试试
命令行请求8000端口:
curl -X POST localhost:8000/v2/models/ensemble/generate -d '{"text_input": "你是谁?", "max_tokens": 50, "bad_words": [], "stop_words": []}'
curl -X POST localhost:8000/v2/models/tensorrt_llm_bls/generate -d '{"text_input": "你是谁?", "max_tokens": 50, "bad_words": [], "stop_words": []}'
bad_words
是生成文本时需要过滤的词汇列表。在自然语言处理(NLP)和生成任务中,有时我们希望模型在生成文本时避免使用某些不合适或不需要的词语,这些词语通常被称为“脏话”或“禁用词”。通过指定 bad_words
参数,我们可以告诉模型在生成文本时避免使用这些词汇。
示例说明
假设我们希望模型生成的文本中避免出现一些特定的词语,比如 “badword1” 和 “badword2”,我们可以在请求中指定这些词语作为 bad_words
参数的值。
例如:
curl -X POST localhost:8000/v2/models/ensemble/generate -d '{"text_input": "Please generate a polite response.", "max_tokens": 50, "bad_words": ["badword1", "badword2"], "stop_words": []}'
在这个请求中,bad_words
参数的值是一个包含两个词语的数组,即 ["badword1", "badword2"]
。这告诉模型在生成响应时避免使用 “badword1” 和 “badword2”。
模型分析器
https://github.com/triton-inference-server/tutorials/tree/main/Conceptual_Guide/Part_3-optimizing_triton_configuration
https://github.com/triton-inference-server/tutorials/tree/main?tab=readme-ov-file
关闭Triton服务
pkill tritonserver
metric
访问:
localhost:8002/metrics
重看Triton服务
这里有个资料:
https://www.atyun.com/59255.html
Triton TensorRT-LLM主要特征及优势:
支持多种深度学习框架
支持多种机器学习框架
模型并发执行(CPU 层次的优化)
动态批处理(Dynamic batching)
有状态模型的序列批处理(Sequence batching)和隐式状态管理(implicit state management)
提供允许添加自定义后端和前/后置处理操作的后端 API
支持使用 Ensembling 或业务逻辑脚本 (BLS)进行模型流水线
HTTP/REST和GRPC推理协议是基于社区开发的KServe协议
支持使用 C API 和 Java API 允许 Triton 直接链接到您的应用程序,用于边缘端场景
支持查看 GPU 利用率、服务器吞吐量、服务器延迟等指标
还有几个问题,留着下次写:
(1)为啥我显存还是占用那么多?
(2)Triton 把api服务写了,我还要怎么自定义出自己的api服务?