当前位置: 首页 > news >正文

网站解析记录值seo自动刷外链工具

网站解析记录值,seo自动刷外链工具,用手机怎么制作app软件,单页面网站卖什么好大模型推理加速调研#xff08;框架、方法#xff09; 大模型推理框架调研总结推理框架TensorRT-LLMllama.cppmnn-llmfastllmmlc-llm 环境搭建部署推理环境llama.cppfastllmmnn-llmvllm vllm_openai_completions.pylmdeployTensorRT-LLM 大模型加速技术总结模型压缩量化… 大模型推理加速调研框架、方法 大模型推理框架调研总结推理框架TensorRT-LLMllama.cppmnn-llmfastllmmlc-llm 环境搭建部署推理环境llama.cppfastllmmnn-llmvllm vllm_openai_completions.pylmdeployTensorRT-LLM 大模型加速技术总结模型压缩量化剪枝知识蒸馏低秩分解 KV CacheFlashAttentionPagedAttentionContinuous batchingSpeculative DecodingMedusa 参考链接 大模型推理框架调研总结 大模型推理加速的目标是高吞吐量、低延迟。吞吐量为一个系统可以并行处理的任务量。延时指一个系统串行处理一个任务时所花费的时间。调研了一些大模型推理的框架。 推理框架 大模型推理加速的目标是降低延迟、提高吞吐量目前开源的端侧推理框架方案主要有 TensorRT-LLM GitHubhttps://github.com/NVIDIA/TensorRT-LLM TensorRT-LLM 是 NVIDIA 用于做 LLMLarge Language Model的可扩展推理方案。该方案是基于 TensorRT 深度学习编译框架来构建、编译并执行计算图并借鉴了许多 FastTransformer 中高效的 Kernels 实现然后利用 NCCL 完成设备之间的通讯。考虑到技术的发展和需求的差异开发者还可以定制算子来满足定制需求比如基于 cutlass 开发定制 GEMM。TensorRT-LLM 是一款致力于提供高性能并不断完善其实用性的 NVIDIA 官方推理方案。 该框架目前主要在云端使用端侧的方案英伟达官方尚未开源据了解目前多家已经开始在Orin中使用TensorRT-LLM来部署大模型。 llama.cpp GitHubhttps://github.com/ggerganov/llama.cpp llama.cpp 是纯C/C实现不依赖任何外部库并且针对x86架构提供了AVX、AVX2和AVX512加速支持。此外它还提供了2、3、4、5、6以及8位量化功能以加快推理速度并减少内存占用。对于大于总VRAM容量的大规模模型该库还支持CPUGPU混合推理模式进行部分加速。本质上llama.cpp的用途在于运行GGUF由GPT生成的统一格式模型。 mnn-llm GitHubhttps://github.com/wangzhaode/mnn-llm mnn-llm是基于MNN实现大预言模型(LLM)在端侧上的部署为了简化并标准化模型转换过程其开发了一个名为 llm-export 的工具。llm-export 工具的核心思想在于对大型语言模型LLM进行了高度抽象建立了一个统一化的导出框架。这个项目的目标是消除将各种 LLM 模型导出到 ONNX 格式的障碍确保无论是何种架构的 LLM 都能通过一个清晰定义的接口进行处理。在 llm-export 中我们定义了一套公用的导出逻辑这意味着对于任何特定的 LLM开发者只需实现模型的加载逻辑。这极大地减少了从多样化的训练环境向 ONNX 模型迁移的复杂性并显著提高了整个导出过程的易用性。模型一旦被成功导出至 ONNX即可利用现有的mnnconvert工具转换到 MNN 格式从而使用MNN完成llm模型的推理。 fastllm GitHubhttps://github.com/ztxz16/fastllm fastllm是纯c实现无第三方依赖的多平台高性能大模型推理库支持功能如下 纯c实现便于跨平台移植可以在安卓上直接编译无论ARM平台X86平台NVIDIA平台速度都较快支持读取Hugging face原始模型并直接量化支持部署Openai api server支持多卡部署支持GPU CPU混合部署支持动态Batch流式输出前后端分离设计便于支持新的计算设备目前支持ChatGLM系列模型Qwen系列模型各种LLAMA模型(ALPACA, VICUNA等)BAICHUAN模型MOSS模型MINICPM模型等支持Python自定义模型结构 mlc-llm GitHubhttps://github.com/mlc-ai/mlc-llm mlc-llm 是一个用于大型语言模型的机器学习编译器和高性能部署引擎。该项目的使命是让每个人都能够在每个人的平台上原生地开发、优化和部署 AI 模型。 mlc-llm 在 MLCEngine 上编译和运行代码 - 一个跨上述平台的统一高性能 LLM 推理引擎。MLCEngine 提供与 OpenAI 兼容的 API可通过 REST 服务器、python、javascript、iOS、Android 使用。 环境搭建部署推理 环境 Ubuntu22.04 模型Qwen2-1.5B llama.cpp git clone gitgithub.com:ggerganov/llama.cpp.git cd llama.cpp git submodule update --init make GGML_CUDA1 ./llama-cli -m /home/lvf6/wyh/Qwen/Qwen2-1.5B-Instruct-GGUF/qwen2-1_5b-instruct-q4_k_m.gguf -ngl 999 -p prompts/chat-with-qwen.txt -i -n -1 -cnv使用llama.cpp部署推理qwen2-1.5B模型会有2G显存的占用 fastllm git clone gitgithub.com:ztxz16/fastllm.git cd fastllm bash install.sh -DUSE_CUDAON ./main -p ~/Qwen2-7B-Instruct/执行有问题 只能问一个问题后面的问题给不出答案 mnn-llm git clone gitgithub.com:wangzhaode/mnn-llm.git cd mnn-llm mkdir build cd build cmake .. -DMNN_CUDAON make -j4 cd .. ./build/cli_demo ./Qwen2-1.5B-Instruct-MNN/config.json对话推理会存在最后出现重复回答的问题 vllm git clone https://github.com/vllm-project/vllm?tabreadme-ov-file cd vllm conda create -n vllm python3.10 conda activate vllm pip install -e .python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2-7B-Instruct-GPTQ-Int4 --quantization gptq6G显存不足以运行Qwen2-7B-Instruct-GPTQ-Int4模型并且从打印信息中可以看到在伏特架构和图灵架构中无法使用FlashAttention-2 转用1.5B模型 python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2-1.5B-Instruct报错提示Bfloat16支持运行在8.0架构以上的显卡 尝试加载Qwen2-1.5B-Instruct-GPTQ-Int4模型 python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2-1.5B-Instruct-GPTQ-Int4 --quantization gptq报错 [rank0]: ValueError: The models max seq len (32768) is larger than the maximum number of tokens that can be stored in KV cache (19472). Try increasing gpu_memory_utilization or decreasing max_model_len when initializing the engine.尝试下面的指令 python -m vllm.entrypoints.openai.api_server --model Qwen/Qwen2-1.5B-Instruct-GPTQ-Int4 --quantization gptq --max_model_len 4096OpenAI请求 【以Qwen2大模型为例】vLLM部署流式推理openai接口调用requests调用_qwen2 openai-CSDN博客 vllm_openai_completions.py from openai import OpenAI openai_api_base http://localhost:8000/v1 openai_api_key EMPTY client OpenAI( api_keyopenai_api_key, base_urlopenai_api_base, ) response client.chat.completions.create(modelQwen/Qwen2-1.5B-Instruct-GPTQ-Int4,messages[{role: system, content: You are a helpful assistant.},{role: user, content: 拉矿物油的罐车装植物油人们食用该食用油后后果是什么这种“投毒”行为相关责任人却没有被法律审判可见法律法规无用该企业是政府部门成立的可见加强监管无用并且该社会问题被隐瞒4年才爆料出来可见社会监督无用如何有效解决该问题},],streamTrue,temperature0, ) for chunk in response:content chunk.choices[0].delta.contentif content:print(content, end, flushTrue) print(\n)打印如下 lmdeploy 官方中文文档欢迎来到 LMDeploy 的中文教程! — lmdeploy 教程 [第五课笔记]LMDeploy 大模型量化部署实践_w4a16量化命令跑多久-CSDN博客 xujinzh.github.io 笔记–LMDeploy 的量化和部署_lmdeploy如何与知识库结合使用-CSDN博客 模型转换(离线转换) 【注】这里不能使用Qwen2-1.5B-Instruct-GPTQ-Int4模型做转换 docker exec -it lmdeploy /bin/bash cd /home/lvf6/disk/wyh/lmdeploy (base) [root8dc861fcc194 lmdeploy]# lmdeploy convert qwen /home/lvf6/disk/wyh/Qwen/Qwen2-1.5B-Instructinput_model_registered_name : qwen2 Device does not support bfloat16. Set float16 forcefully output_model_registered_name: fp16 remove workspace in directory workspace create workspace in directory workspace turbomind model config: {model_name: qwen,model_arch: Qwen2ForCausalLM,tensor_para_size: 1,head_num: 12,kv_head_num: 2,vocab_size: 151936,num_layer: 28,inter_size: 8960,norm_eps: 1e-06,attn_bias: 1,start_id: 151643,end_id: 151645,session_len: 32776,weight_type: fp16,rotary_embedding: 128,rope_theta: 1000000.0,size_per_head: 128,group_size: 0,max_batch_size: 64,max_context_token_num: 1,step_length: 1,cache_max_entry_count: 0.8,cache_block_seq_len: 64,cache_chunk_size: -1,enable_prefix_caching: false,num_tokens_per_iter: 0,max_prefill_iters: 1,extra_tokens_per_iter: 0,use_context_fmha: 1,quant_policy: 0,max_position_embeddings: 32768,original_max_position_embeddings: 0,rope_scaling_type: ,rope_scaling_factor: 0.0,use_dynamic_ntk: 0,low_freq_factor: 1.0,high_freq_factor: 1.0,use_logn_attn: 0,lora_policy: ,lora_r: 0,lora_scale: 0.0,lora_max_wo_r: 0,lora_rank_pattern: ,lora_scale_pattern: } *** splitting layers.0.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.0.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.0.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.0.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.0.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.0.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.0.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.1.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.1.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.1.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.1.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.1.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.1.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.1.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.2.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.2.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.2.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.2.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.2.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.2.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.2.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.3.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.3.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.3.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.3.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.3.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.3.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.3.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.4.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.4.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.4.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.4.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.4.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.4.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.4.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.5.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.5.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.5.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.5.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.5.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.5.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.5.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.6.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.6.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.6.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.6.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.6.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.6.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.6.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.7.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.7.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.7.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.7.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.7.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.7.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.7.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.8.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.8.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.8.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.8.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.8.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.8.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.8.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.9.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.9.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.9.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.9.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.9.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.9.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.9.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.10.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.10.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.10.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.10.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.10.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.10.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.10.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.11.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.11.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.11.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.11.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.11.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.11.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.11.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.12.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.12.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.12.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.12.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.12.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.12.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.12.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.13.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.13.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.13.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.13.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.13.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.13.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.13.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.14.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.14.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.14.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.14.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.14.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.14.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.14.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.15.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.15.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.15.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.15.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.15.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.15.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.15.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.16.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.16.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.16.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.16.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.16.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.16.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.16.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.17.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.17.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.17.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.17.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.17.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.17.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.17.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.18.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.18.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.18.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.18.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.18.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.18.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.18.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.19.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.19.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.19.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.19.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.19.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.19.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.19.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.20.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.20.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.20.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.20.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.20.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.20.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.20.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.21.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.21.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.21.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.21.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.21.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.21.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.21.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.22.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.22.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.22.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.22.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.22.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.22.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.22.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.23.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.23.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.23.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.23.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.23.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.23.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.23.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.24.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.24.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.24.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.24.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.24.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.24.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.24.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.25.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.25.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.25.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.25.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.25.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.25.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.25.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.26.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.26.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.26.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.26.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.26.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.26.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.26.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 *** splitting layers.27.attention.w_qkv.weight, shapetorch.Size([1536, 2048]), split_dim-1, tp1 *** splitting layers.27.attention.wo.weight, shapetorch.Size([1536, 1536]), split_dim0, tp1 *** splitting layers.27.attention.w_qkv.bias, shapetorch.Size([1, 2048]), split_dim-1, tp1 ### copying layers.27.attention.wo.bias, shapetorch.Size([1536]) *** splitting layers.27.feed_forward.w1.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.27.feed_forward.w3.weight, shapetorch.Size([1536, 8960]), split_dim-1, tp1 *** splitting layers.27.feed_forward.w2.weight, shapetorch.Size([8960, 1536]), split_dim0, tp1 Convert to turbomind format: 100%|█████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 28/28 [00:0200:00, 12.63it/s]执行完成后将会在当前目录生成一个 workspace 的文件夹。这里面包含的就是 TurboMind 和 Triton “模型推理”需要到的文件。 目录如下 TurboMind 推理命令行本地对话 (base) [root8dc861fcc194 lmdeploy]# lmdeploy chat --backend turbomind ./workspace显存占用 使用nvidia-smi命令查看发现lmdeploy使用TurboMind 推理qwen2-1.5b模型会占用5G显存 静态推理性能测试 我们把推理引擎在固定 batch、固定输入输出 token 数量的前提下的推理称之为静态推理。 评测脚本是 profile_generation.py在运行此脚本前请安装 lmdeploy 预编译包并下载评测脚本 测量指标 LMDeploy 统计首token延时first_token_latency、token 吞吐量tokens/s每个token延时的百分位数据P50P75P95P99、GPU mem 等测试结果。 first_token_latency 只有在流式推理的情况下才会输出。 吞吐量的计算公式为 [ token吞吐量 生成的token数量 / 总时间 ] 总时间包括 prefill 时间。 测试过程中节点上所有的显卡不要运行其他任何程序否则 GPU mem 的统计会不准确。 测量方法 我们以 internlm/internlm-7b 为例分别介绍测试 LMDeploy 两个推理引擎 turbomind 和 pytorch 的静态推理性能测试方法 Turbomind 引擎 cd lmdeploy/benchmark python3 profile_generation.py ./workspace**加粗样式**TensorRT-LLM docker构建 git clone https://github.com/NVIDIA/TensorRT-LLM.git cd TensorRT-LLM git checkout tags/v0.7.0 -b release/0.7.0 git submodule update --init --recursive git lfs install git lfs pull cd TensorRT-LLM/docker make release_build【注】不要使用main分支main分支英伟达内部也没经过测试处于不稳定的状态亲测连docker都构建不出来光是构建这个docker就花了一天的时间…换了release分支才构建成功就说Tensorrt-LLM有多难用吧 模型转换 python convert_checkpoint.py --model_dir /home/lvf6/disk/wyh/Qwen/Qwen2-1.5B-Instruct --output_dir ./trt_engines/qwen2-1.5b/fp16/1-gpu/ --dtype float16发现使用convert_checkpoint.py转换模型时显存不够更换0.5B模型 git clone https://huggingface.co/Qwen/Qwen2-0.5B-Instructpython convert_checkpoint.py --model_dir /home/lvf6/disk/wyh/Qwen/Qwen2-0.5B-Instruct/ --output_dir ./trt_engines/qwen2-0.5b/fp16/1-gpu/ --dtype float16trtllm-build --checkpoint_dir ./trtllm_qwen2_0.5b_fp16_1_gpu/ --output_dir ./trt_engines/qwen2-0.5b/fp16/1-gpu/ --gemm_plugin float16遇到报错 https://github.com/NVIDIA/TensorRT-LLM/issues/1967 结论 因为RTX2060显卡只有6G显存因此无法转换0.5B大小以上的模型在更换为qwen2-0.5B模型之后又会遇到上述问题官方也还没有给出具体的解决方案因为各种限制在RTX2060上暂时无法使用TensorRT-LLM部署大模型 大模型加速技术总结 模型压缩 近年来随着Transformer、MOE架构的提出使得深度学习模型轻松突破上万亿规模参数从而导致模型变得越来越大因此为了将大模型部署在端侧设备中我们需要使用一些大模型压缩技术来降低模型部署的成本并提升模型的推理性能。而大模型压缩主要分为如下几类 量化Quantization剪枝Pruning知识蒸馏Knowledge Distillation低秩分解Low-Rank Factorization 量化 模型量化通过以更少的位数表示浮点数据模型量化可以减少模型尺寸进而减少在推理时的内存消耗并且在一些低精度运算较快的处理器上可以增加推理速度。 计算机中不同数据类型的占用比特数及其表示的数据范围各不相同。可以根据实际业务需求将原模型量化成不同比特数的模型一般深度神经网络的模型用单精度浮点数表示如果能用有符号整数来近似原模型的参数那么被量化的权重参数存储大小就可以降到原先的四分之一用来量化的比特数越少量化后的模型压缩率越高。 工业界目前最常用的量化位数是8比特低于8比特的量化被称为低比特量化。1比特是模型压缩的极限可以将模型压缩为1/32。 大模型量化的对象主要包括以下几个方面 权重weightweight的量化是最常规也是最常见的。量化weight可达到减少模型大小内存和占用空间。激活activation实际中activation往往是占内存使用的大头因此量化activation不仅可以大大减少内存占用。更重要的是结合weight的量化可以充分利用整数计算获得性能提升。KV cache量化 KV 缓存对于提高长序列生成的吞吐量至关重要。 另外根据量化数据表示的原始数据范围是否均匀还可以将量化方法分为线性量化和非线性量化。实际的深度神经网络的权重和激活值通常是不均匀的因此理论上使用非线性量化导致的精度损失更小但在实际推理中非线性量化的计算复杂度较高通常使用线性量化。 根据量化参数s和z的共享范围即量化粒度量化方法可以分为逐层量化per-tensor这是最简单的一种方式也是范围最大的粒度。以一层网络为量化单位每层网络一组量化参数 逐通道量化per-token per-channel以一层网络的每个量化通道为单位每个通道单独使用一组量化参数。逐通道量化由于量化粒度更细能获得更高的量化精度但计算也更复杂。 per-token针对激活 x 而言每行对应一个量化系数。per-channel针对权重 w 而言每列对应一个量化系数。 逐组量化per-group,以组为单位每个group使用一组s和z它的粒度处于 per-tensor 和 per-channel 之间。当 group1 时逐组量化与逐层量化等价当 groupnum_filters如dwDepthwise将卷积核变成单通道时逐组量化与逐通道量化等价。 根据应用量化压缩的阶段可以将模型量化分为量化感知训练Quantization Aware Training, QAT在模型训练过程中加入伪量化算子通过训练时统计输入输出的数据范围可以提升量化后模型的精度适用于对模型精度要求较高的场景其量化目标无缝地集成到模型的训练过程中。这种方法使LLM在训练过程中适应低精度表示增强其处理由量化引起的精度损失的能力。这种适应旨在量化过程之后保持更高性能。量化感知微调Quantization-Aware Fine-tuningQAF在微调过程中对LLM进行量化。主要目标是确保经过微调的LLM在量化为较低位宽后仍保持性能。通过将量化感知整合到微调中以在模型压缩和保持性能之间取得平衡。训练后量化Post Training Quantization, PTQ在LLM训练完成后对其参数进行量化只需要少量校准数据适用于追求高易用性和缺乏训练资源的场景。主要目标是减少LLM的存储和计算复杂性而无需对LLM架构进行修改或进行重新训练。PTQ的主要优势在于其简单性和高效性。但PTQ可能会在量化过程中引入一定程度的精度损失。 大模型量化感知训练方法LLM-QAT论文LLM-QAT: Data-Free Quantization Aware Training for Large Language Models利用预训练模型生成的结果来实现无数据蒸馏。此外LLM-QAT不仅量化权重和激活还量化了KV缓存。这个策略旨在增强吞吐量并支持更长的序列依赖。LLM-QAT能够将带有量化权重和KV缓存的LLaMA模型蒸馏为仅有4比特的模型。这一突破性的结果论证了生产准确的4比特量化的LLM的可行性。详情请查看之前的文章大模型量化感知训练开山之作LLM-QAT 大模型量化感知微调方法PEQA论文Memory-efficient fine-tuning of compressed large language models via sub-4-bit integer quantization这是一种新的量化感知 PEFT 技术可以促进模型压缩并加速推理。它采用了双阶段过程运行。在第一阶段每个全连接层的参数矩阵被量化为低比特整数矩阵和标量向量。在第二阶段对每个特定下游任务的标量向量进行微调。这种策略大大压缩了模型的大小从而降低了部署时的推理延迟并减少了所需的总体内存。同时快速的微调和高效的任务切换成为可能。QLORA论文 QLORA: Efficient Finetuning of Quantized LLMs引入了新的数据类型NF4、双重量化和分页优化器等创新概念。这些想法旨在在不影响性能的情况下节省内存。QLORA使得微调LLaMA-65B大模型仅需48G显存同时基本不会影响微调效果。详情请查看之前的文章大模型参数高效微调技术原理综述五-LoRA、AdaLoRA、QLoRA 大模型训练后量化方法 PTQ 的主要目标是减少 LLM 的存储和计算复杂性而无需对 LLM 架构进行修改或重新训练。PTQ 的主要优势在于其简单和高效。然而值得注意的是PTQ可能会在量化过程中引入一定程度的精度损失。大模型的量化方法按照量化对象可分为权重量化和全量化(权重和激活量化)。 权重量化方法主要包括LUT-GEMM论文nuqmm: Quantized matmul for efficient inference of large-scale generative language models通过仅对权重进行量化以及使用BCQ格式在LLM中优化矩阵乘法通过提高计算效率来增强延迟降低和性能。LLM.int8()论文LLM.int8(): 8-bit Matrix Multiplication for Transformers at Scale采用混合精度分解的量化方法。先做了一个矩阵分解对绝大部分权重和激活用8bit量化vector-wise。对离群特征的几个维度保留16bit对其做高精度的矩阵乘法。 ZeroQuant 论文ZeroQuant: Efficient and Affordable Post-Training Quantization for Large-Scale Transformers对权重做group-wise对激活值做token-wise。用逐层知识蒸馏缓解精度损失原网络做老师量化后的网络做学生。和W8A8的普通方法做比较在BERT和GPT3-style模型上精度更好还能把权重量化到4bit但加速效果糟糕。GPTQ (论文GPTQ: ACCURATE POST-TRAINING QUANTIZATION FOR GENERATIVE PRE-TRAINED TRANSFORMERS) 对某个 block 内的所有参数逐个量化每个参数量化后需要适当调整这个 block 内其他未量化的参数以弥补量化造成的精度损失。GPTQ 量化需要准备校准数据集。Dettmers和Zettlemoyer 通过分析推理缩放定律论文The case for 4-bit precision: k-bit inference scaling laws深入探讨了LLM中模型大小和比特精度之间在零样本性能方面的权衡。他们在各种LLM家族之间进行了广泛的实验在全部的模型比特数和零样本准确性之间发现4比特精度几乎普遍是实现平衡的最佳选择。 AWQ 论文AWQ: Activation-aware Weight Quantization for LLM Compression and Acceleration发现对于LLM的性能权重并不是同等重要的通过保留1%的显著权重可以大大减少量化误差。在此基础上AWQ采用了激活感知方法考虑与较大激活幅度对应的权重通道的重要性这在处理重要特征时起着关键作用。该方法采用逐通道缩放技术来确定最佳缩放因子从而在量化所有权重的同时最小化量化误差。 OWQ 论文OWQ: Lessons learned from activation outliers for weight quantization in large language models通过分析激活异常如何放大权重量化中的误差引入了混合精度量化方案将更高的精度应用于易受激活异常影响的权重。 SpQR论文SpQR: A Sparse-Quantized Representation for Near-Lossless LLM Weight Compression确定并隔离了异常权重将其存储在更高的精度中并将所有其他权重压缩为3-4比特。 全量化(权重和激活量化)方法主要包括SmoothQuant论文SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models解决了量化激活的挑战。SmoothQuant观察到不同的token在它们的通道上展示出类似的变化引入了逐通道缩放变换有效地平滑了幅度使得模型更易于量化。 RPTQ论文RPTQ: Reorder-based Post-training Quantization for Large Language Models揭示了不同通道之间不均匀范围的挑战以及异常值的存在所带来的问题。为了解决这个问题RPTQ将通道策略性地分组为簇进行量化有效地减轻了通道范围的差异。此外它将通道重排集成到层归一化操作和线性层权重中以最小化相关的开销。OliVe论文OliVe: Accelerating Large Language Models via Hardware-friendly Outlier-Victim Pair Quantization进一步采用了 outlier-victim 对OVP量化并在低硬件开销和高性能增益的情况下局部处理异常值因为它发现异常值很重要而其旁边的正常值却不重要。Outlier Suppression论文Outlier Suppression: Accurate quantization of large language models by equivalent and optimal shifting and scaling通过确认激活中的有害异常呈现出不对称分布主要集中在特定通道中。因此引入了一种新的策略涉及通道级的平移和缩放操作以纠正异常的不对称呈现并减轻问题通道的影响并定量分析了平移和缩放的最佳值同时考虑了异常的不对称性以及下一层权重引起的量化误差。ZeroQuant-FP论文ZeroQuant-FP: A Leap Forward in LLMs Post-Training W4A8 Quantization Using Floating-Point Formats探索了浮点FP量化的适用性特别关注FP8和FP4格式。研究揭示对于LLMFP8激活在性能上持续优于INT8而在权重量化方面FP4在性能上与INT4相比具有可比性甚至更优越。为了解决由权重和激活之间的差异引起的挑战ZeroQuant-FP要求所有缩放因子为2的幂并将缩放因子限制在单个计算组内。值得注意的是ZeroQuant-FP还集成了Low Rank Compensation (LoRC) 策略以进一步增强其量化方法的有效性。 剪枝 模型剪枝Model Pruning是一种用于减少神经网络模型参数数量和计算量的技术。如果说“量化”是通过改变权重和激活值的表现形式从而让内存占用变小和计算变快的话“剪枝”则是直接“删除”掉模型中没有意义的或者意义较小的权重来减少推理计算量的过程。剪枝通过识别和去除在训练过程中对模型性能影响较小的参数或连接从而实现模型的精简和加速。 通常模型剪枝可以分为两种类型 结构化剪枝Structured Pruning非结构化剪枝Unstructured Pruning 结构化剪枝和非结构化剪枝的主要区别在于剪枝目标和由此产生的网络结构。结构化剪枝根据特定规则删除连接或层结构同时保留整体网络结构。而非结构化剪枝会剪枝各个参数从而产生不规则的稀疏结构。 模型剪枝的一般步骤包括 训练初始模型首先需要训练一个初始的大模型通常是为了达到足够的性能水平。评估参数重要性使用某种评估方法如权重的绝对值、梯度信息等来确定模型中各个参数的重要性。剪枝根据评估结果剪枝掉不重要的参数或连接可以是结构化的或非结构化的。修正和微调进行剪枝后需要进行一定的修正和微调以确保模型的性能不会显著下降。 模型剪枝可以带来多方面的好处包括减少模型的存储需求、加速推理速度、减少模型在边缘设备上的资源消耗等。然而剪枝可能会带来一定的性能损失因此需要在剪枝前后进行适当的评估和调整。 大模型的非结构化剪枝方法主要有 SparseGPT(论文SparseGPT: Massive Language Models Can be Accurately Pruned in One-Shot)LoRAPrune(论文LoRAPrune: Pruning Meets Low-Rank Parameter-Efficient Fine-Tuning) 大模型的结构化剪枝方法主要有:LLM-Pruner(论文LLM-Pruner: On the Structural Pruning of Large Language Models) 知识蒸馏 知识蒸馏是一种机器学习模型压缩方法它用于将大型模型教师模型的知识迁移到较小的模型学生模型中。 知识蒸馏KD也被称为教师-学生神经网络学习算法是一种有价值的机器学习技术旨在提高模型性能和泛化能力。 它通过将知识从复杂的模型称为教师模型转移到更简单的模型称为学生模型来实现这一点。 KD背后的核心思想是将教师模型的综合知识转化为更精简、更有效的表示。 本文我们将概述利用LLM作为教师的蒸馏方法。根据这些方法是否将LLM的涌现能力EA提炼成小语言模型SLM来对这些方法进行分类。 因此我们将这些方法分为两个不同的类别标准 KD 和基于 EA 的 KD。 为了直观地表示下图提供了LLM知识蒸馏的简要分类。 标准知识蒸馏 MINILLM 论文Knowledge Distillation of Large Language ModelsGKD论文GKD: Generalized Knowledge Distillation for Auto-regressive Sequence Models 基于涌现能力的知识蒸馏 基于 EA 的 KD 不仅仅迁移 LLM 的常识还包括蒸馏他们的涌现能力。 与 BERT330M和 GPT-21.5B等较小模型相比GPT-3175B和 PaLM540B等 LLM 展示了独特的行为。 这些LLM在处理复杂的任务时表现出令人惊讶的能力称为“涌现能力”。 涌现能力包含三个方面包括上下文学习 (ICL)、思维链 (CoT) 和指令遵循 (IF)。 如图三所示它提供了基于EA的知识蒸馏概念的简明表示。 上下文学习蒸馏元上下文调优 (Meta-ICT)多任务上下文调优 (Multitask-ICT) 思维链蒸馏MT-COT 论文Explanations from Large Language Models Make Small Reasoners BetterFine-tune CoT 论文Large language models are reasoning teachersSOCRATIC CoT论文Distilling Reasoning Capabilities into Smaller Language ModelsDISCO论文DISCO: Distilling Counterfactuals with Large Language ModelsSCOTT论文SCOTT: Self-Consistent Chain-of-Thought Distillation 指令遵循蒸馏Lion 论文Lion: Adversarial Distillation of Closed-Source Large Language Model 低秩分解 低秩分解是一种将高维数据分解为低维矩阵的技术它可以通过减少矩阵的秩来降低模型复杂度。在大规模神经网络模型中权重矩阵通常具有很高的秩通过低秩分解可以将这些权重矩阵分解为低秩矩阵从而实现模型的压缩。 KV Cache 生成式generative模型的推理过程很有特点我们给一个输入文本模型会输出一个回答长度为N其实该过程中执行了N次推理过程。即GPT类模型一次推理只输出一个token输出token会与输入tokens 拼接在一起然后作为下一次推理的输入这样不断反复直到遇到终止符如下所示 step 0 input: Lionel Messi is a player step 1 input: Lionel Messi is a player who step 2 input: Lionel Messi is a player who has step 3 input: Lionel Messi is a player who has been step 4 input: Lionel Messi is a player who has been a step 5 input: Lionel Messi is a player who has been a key step 6 input: Lionel Messi is a player who has been a key part step 7 input: Lionel Messi is a player who has been a key part of step 8 input: Lionel Messi is a player who has been a key part of the step 9 input: Lionel Messi is a player who has been a key part of the team step 10 input: Lionel Messi is a player who has been a key part of the teams step 11 input: Lionel Messi is a player who has been a key part of the teams success step 12 input: Lionel Messi is a player who has been a key part of the teams success. step 13 input: Lionel Messi is a player who has been a key part of the teams success.Input: Lionel Messi is a Output: Lionel Messi is a player who has been a key part of the teams success.可以看出每次推理过程的输入tokens都变长了导致推理FLOPs随之增大有方法实现推理过程的FLOPs基本恒定不变或变小吗那就是KV Cache。 看上面图和公式我们可以得出结论 当前计算方式存在大量冗余计算。 A t t k Att_k Attk​ 只与 Q k Q_k Qk​ 和历史KV有关。推理第 x k x_k xk​ 个字符的时候只需要输入字符 x k − 1 x_{k-1} xk−1​即可。 我们每一步其实之需要根据 Q k Q_k Qk​ 计算 A t t k Att_k Attk​ 就可以之前已经计算的Attention完全不需要重新计算。但是 K 和 V 是全程参与计算的所以这里我们需要把每一步的 K,V 缓存起来这样可以大大节省计算开销。 下面的动图展示了使用KV Cache和不使用KV Cache的对比。 FlashAttention 当输入序列sequence length较长时Transformer的计算过程缓慢且耗费内存这是因为self-attention的时间复杂度和空间复杂度会随着sequence length的增加成二次方增长。GPU中存储单元主要有HBM和SRAMGPU将数据从显存HBM加载至on-chip的SRAM中然后由SM读取并进行计算计算结果再通过SRAM返回给显存, HBM容量大但是访问速度慢SRAM容量小却有着较高的访问速度。普通的Attention的计算过程如下需要多次访问HBMFlash Attention的目的就是通过分片算子融合矩阵乘法和Softmax减少对HBM的访问。 我们都知道flashAttention是优化了计算过程中的访存HBM的过程那么我们先来看下标准Attention的计算访存 首先从HBM中读取完整的Q和K矩阵每个大小为N x d计算点积得到相似度得分S大小为N x N需要进行 O ( N × d N 2 ) O(N×d N^2) O(N×dN2)次HBM访问。 其次计算注意力权重P大小为N x N时需要对S进行softmax操作这需要进行 O ( N 2 ) O(N^2) O(N2)次HBM访问。 最后将注意力权重P和值向量V每个大小为N x d加权求和得到输出向量O大小为N x d时需要进行O(Nd)次HBM访问。 因此标准 Attention 算法的总HBM访问次数为 O ( N × d N 2 ) O(N×d N^2) O(N×dN2)。当N比较大时总的HBM访问次数可能会比较昂贵。 从上面可以看出标准Attention算法在GPU内存分级存储的架构下存在以下缺陷 过多对HBM的访问如S、P需要在存入HMB后又立即被访问HBM带宽较低从而导致算法性能受限S、P需要占用 O ( N 2 ) O(N^2) O(N2)的存储空间显存占用较高 基于之前的思路我们可以有一个比较简单的实现方式 之所以存在大量的访存HBM一个原因是在Attention的计算中存在三个kernel每个kernel的计算过程都存在从HBM读取数据计算完成后还要写回HBM。如果我们将三个Kernel融合为一个则就可以减少部分的访问HBM的次数。在计算过程中要尽量的利用SRAM进行计算避免访问HBM操作。 然而我们都知道虽然SRAM的带宽较大但其计算可存储的数据量较小。如果我们采取“分治”的策略将数据进行Tilling处理放进SRAM中进行计算由于SRAM较小当sequence length较大时sequence会被截断从而导致标准的SoftMax无法正常工作。 那么flashAttention是如何进行实现的呢 Flash attention基本上可以归结为两个主要点:Tiling (在向前和向后传递时使用)-基本上将NxN softmax/scores矩阵分块成块。Recomputation (重算仅在向后传递中使用) Tiling平铺其核心思想是将原始的注意力矩阵分解成更小的子矩阵然后分别对这些子矩阵进行计算只要这个子矩阵的大小可以在SRAM内存放那么不就可以在计算过程中只访问SRAM了。 然而在Attention中softmax需要将所有的列耦合在一起计算如何解决呢 flashAttention提出了分块SoftMax算法确保了整个Flash Attention的正确性。 对于向量[x1, x2, …, xd], 原生softmax的计算过程如下 在实际硬件中因为浮点数表示的范围是有限的对于FP16来说当xi≥11时exp(xi)就会变成inf发生数据上溢的问题。 为了确保数值计算的稳定性避免溢出问题通常采用一种称为“safe softmax”的计算策略。在此方法中通过减去最大值来缩放输入数据以保证数值的相对稳定性。 所以说现有所有的深度学习框架中都采用了“safe softmax”这种计算方式其计算公式为如下。 safe softmax基本计算示例 safe softmax tiling计算示例结果跟基本计算示例一致 有了softmax tiling的基础以后在执行的时候可以对 Q 、K 、V 三个矩阵进行分块操作并行计算了如下图所示 PagedAttention 对于训练好的模型一种常用的部署方式是将其打包成一个推理服务server它接收客户端发送来的请求request读取请求中的数据prompt来做推理。一个请求中可以只有1个prompt也可以包含多个prompt。 在常规的推理框架中当我们的服务接收到一条请求时它会为这条请求中的prompts分配gpu显存空间其中就包括对KV cache的分配。由于推理所生成的序列长度大小是无法事先预知的所以大部分框架会按照(batch_size, max_seq_len)这样的固定尺寸在gpu显存上预先为一条请求开辟一块连续的矩形存储空间。然而这样的分配方法很容易引起“gpu显存利用不足”的问题进而影响模型推理时的吞吐量。我们来具体看一个例子。 下图展示了一个常规的推理框架是如何为请求中的prompt在gpu显存上分配KV cache的。在本例中我们假设一个请求只发送1条prompt本例中共有3条请求 仔细观察这3条prompt的KV cache排布你是不是隐约觉得这种排布似乎没有充分利用起gpu的显存 浅色块观察图中的浅色块它是prefill阶段prompt的KV cache是无论如何都会被使用的空间它不存在浪费。中色块观察图中的中色块它是decode阶段的KV cache其中表示序列生成的截止符。虽然这些中色块最终都会被我们用上但是在decode阶段一个个token生成时我们并不能预知哪些块会被最终用上。例如对于prompt2当你生成when的时候你无法知道下一个会生成还是会生成别的词。所以这些中色块都是一种“潜在的浪费”我们称中色块的部分为预留碎片reservation fragment。深色块观察图中的深色块它也是decode阶段的KV cache但直到序列生成完毕它都没有被用上。由于这些深色块是预留的KV cache的一部分所以我们称其为内部碎片internal fragment。灰色块观察图中的灰色块它不是我们预留的KV cache的一部分且最终也没有被用上我们称这些灰色块为外部碎片external fragment。想象一下此时新来了一条prompt4它也要求显存中的8个格子作为KV cache。此时你的显存上明明有9个空格子但因为它们是不连续的碎片所以无法被prompt4所使用。这时prompt4的这条请求只好在队列中等待直到gpu上有足够显存资源时再进行推理这不就对模型推理的吞吐量造成显著影响了吗 PagedAttention是受操作系统虚拟内存和分页思想启发对kv cache所占空间的分页管理是一个典型的以内存空间换计算开销的手段虽然kv cache很重要但是kv cache所占的空间也确实是大且有浪费的所以出现了pagedattention来解决浪费问题。kv cache大小取决于seqlen然而这个东西对于每个batch里面的seq来说是变化的毕竟不同的人输入不同长度的问题模型有不同长度的答案回答kv cache统一按照max seq len来申请造成现有decoder推理系统浪费了很多显存。 PagedAttention将每个序列的KV缓存分成多个块在初始化阶段它预先分配一大块显存并划分成小块即图中的 Physical KV cache blocks真正存储 KV cache 的空间每个块称为 Physical block可以存储 block_size 个 token 所需的 KV cache并创建块表Block table用于将 Logical KV cache blocks每个块称为 Logical block用于存储 token 值 映射到 Physical KV cache blocks。 预分配显存并分块以及创建块表 假设接收到的请求的 prompt 是 “Alan Turing is a computer scientist”它为该请求分配 Logical KV block 以及 Physical KV cache block并通过块表将两者关联在一起。如图 4 所示“Alan Turing is a” 逻辑上存储在 Logical KV cache blocks 中的 Block 0实际上是被存储在 Physical KV cache block 的 Block 7两者通过块表关联在一起其中 Filled slots 表示该 块已存储的 token 数。 接下来开始生成第一个 token “and”它存储在 Logical KV cache blocks 的 Block 1实际存储在 Physical KV cache block 的 Block 1同时更新 Filled slots 为 3如图 5 所示。 生成第二个 token “mathematician”如图 6 所示。 生成第三个 token “renowed”由于 Block 1 已经满了已经存了 4 个 token需要新分配一个块用来存放新 token “renowed”。 同样生成第四个 token “for”。 从上面的介绍中可以看到PagedAttention 可以很好地解决现有推理系统 KV cache 产生的内外部碎片。 vLLM在显存利用上的改进效果VS 其它推理框架 Continuous batching 静态批处理在第一遍迭代左中每个序列从提示词黄中生成一个标记蓝色。经过几轮迭代右后完成的序列具有不同的尺寸因为每个序列在不同的迭代结束时产生不同的结束序列标记红色。尽管序列3在两次迭代后完成但静态批处理意味着 GPU 将在批处理中的最后一个序列完成。 动态批处理一旦批中的一个序列完成生成就可以在其位置插入一个新的序列从而实现比静态批处理更高的GPU利用率。 Speculative Decoding 投机采样的关键在于利用小模型多次推理单个字让大模型进行多字预测从而提升整体推理效率。每次小模型的单字推理耗时远远小于大模型因此投机采样能够有效地提高推理效率。这种方法的优 势在于通过蒸馏学习和投机采样可以在减小模型规模的同时保持较高的预测效果和推理速度从而在实际部署中获得更好的性能优化。 from transformers import AutoModelForCausalLM, AutoTokenizer import torchprompt Alice and Bob checkpoint EleutherAI/pythia-1.4b-deduped assistant_checkpoint EleutherAI/pythia-160m-deduped device cuda if torch.cuda.is_available() else cputokenizer AutoTokenizer.from_pretrained(checkpoint) inputs tokenizer(prompt, return_tensorspt).to(device) # ------------------------------------------------------------------------------------ model AutoModelForCausalLM.from_pretrained(checkpoint).to(device) assistant_model AutoModelForCausalLM.from_pretrained(assistant_checkpoint).to(device) # ------------------------------------------------------------------------------------ outputs model.generate(**inputs, assistant_modelassistant_model) print(tokenizer.batch_decode(outputs, skip_special_tokensTrue)) # [Alice and Bob are sitting in a bar. Alice is drinking a beer and Bob is drinking a]Medusa 一次生成多个词相对于投机采样使用一个小模型一次生成多个词主要思想是在正常的LLM的基础上增加几个解码头并且每个头预测的偏移量是不同的比如原始的头预测第i个token而新增的medusa heads分别为预测第i1i2…个token。如上图并且每个头可以指定topk个结果这样可以将所有的topk组装成一个一个的候选结果最后选择最优的结果。 1、多头美杜莎预测记录logits 2、预测的token组合输入大模型token的组合太多了每个分别输入大模型判断耗时太长Madusa提出了下图所示的树形注意力机制预测的所有token可以同时输入进大模型输出logits概率进行判别是否接受以及接收长度。 3、选择最优重复1 多头美杜莎还会面临的一个问题是随着美杜莎头数量增加top-k的树状分支也将会以指数增长造成庞大的计算开销。此外许多基础和微调模型并没有开放其训练数据集因此多头美杜莎面临的另一大问题是使用什么数据来训练美杜莎头。 参考链接 LLM量化笔记 https://medium.com/joaolages/kv-caching-explained-276520203249 https://bendi.news/wxnews/clryzf6gq0020hdnyjyb2e373 极智AI | 大模型优化之KV Cache PagedAttention(vLLM)—更快地推理你的GPT 拆解 FlashAttention LLM十七从 FlashAttention 到 PagedAttention, 如何进一步优化 Attention 性能 极智AI | 大模型优化技术PagedAttention PagedAttention/KV cache–大模型推理服务框架vLLM要点简析 (中) PagedAttention(vLLM)—更快地推理你的GPT Continuous Batching一种提升 LLM 部署吞吐量的利器 https://www.anyscale.com/blog/continuous-batching-llm-inference https://cloud.tencent.com/developer/article/2350466 https://huggingface.co/blog/zh/assisted-generation Transformers是如何实现大模型的投机采样的
http://www.dnsts.com.cn/news/37427.html

相关文章:

  • 做的网站不能放视频软件站长工具流量统计
  • 企业网站开发成本网页制作的常用开发工具是什么
  • 荥阳做网站推广代理销售公司如何注册
  • 网站文章页301重定向怎么做江苏省住房和城乡建设厅 官方网站
  • 营销展示型网站模板怎么自己搭建小程序
  • 罗湖网站建设公司高清视频网络服务器
  • 如何自己开个网站平台网站顶部小图标怎么做
  • 可以在公司局域网做网站吗wordpress主页制作
  • 做商城网站那个好济南网站优化推广
  • 注册网站账号审核不通过无法登陆怎么办快速域名网站备案
  • 行业网站推广外包无锡电子商城网站设计
  • 需要网站建设的人多吗什么样的网站高大上
  • 如何做自己的业务网站邯郸网站推广怎么做
  • python做网站好处织梦广告网站模板免费下载
  • 网站开发用哪种语言wordpress相册插件中文
  • 上海阔达网站建设公司泉州建站模板厂家
  • 低价网站建设策划内容浙江工程信息网
  • wordpress 多站点开启防城港网站设计公司
  • 自己如何做网站关键词排名威海网站优化公司
  • 天行健公司网站建设无锡网页制作公司
  • quiz在哪个网站做织梦网站怎么上传视频
  • 大连网站设计公司排名抖音推广外包公司
  • 阿克苏建设局网站doc文件打开乱码怎么办
  • 精品资源共享课程网站建设个体户核名查询系统
  • 个人网站有什么内容做网站优化词怎么选择
  • 网站建设格局抚州做网站价格多少
  • dremwear做网站编程课网课哪个好
  • 2019做网站找代理产品上哪个平台
  • 沈阳模板建站wordpress创建企业网站
  • 网站的类型大全江苏省建设安全协会网站