【免费下载链接】InternVL3-38B-Instruct
InternVL3-38B-Instruct 是 OpenGVLab 开源的 38B 参数多模态大模型(MLLM),由 6B 视觉编码器 InternViT-6B + Qwen2.5-32B 语言模型组成。单张消费级甚至 48G 专业卡都装不下它,官方在 README.md 中给出了split_model多 GPU 切分方案。本文带你从零理解这套多卡部署原理:device_map是怎么算出来的、为什么第一张卡按"半张卡"对待、首尾层为什么必须同卡,最后给出一套可直接上手的加载与推理流程,帮助你用多张 80GB GPU 稳定跑起这个模型。
为什么单卡跑不动 InternVL3-38B-Instruct?
先算一笔显存账:
| 组成部分 | 参数量 | bf16 权重占用 |
|---|---|---|
| LLM 语言模型(Qwen2.5-32B) | ~32B | ~64 GB |
| ViT 视觉编码器(InternViT-6B) | ~6B | ~12 GB |
| MLP 投影层 + 推理 KV Cache | — | 数 GB |
- bf16 加载总计约 80 GB 以上,单张 80GB 显卡连权重都放不下,更别提激活值与 KV Cache;
- 38B 模型总参数(model-00001-of-00016.safetensors 等 16 个分片,可用 model.safetensors.index.json 查看各参数分布)远超单卡容量。
因此必须用张量级/层级的多卡切分(model parallel):把 LLM 的 64 个 Transformer 层(config.json 中num_hidden_layers: 64)拆到多张 GPU 上。
split_model 切分原理拆解
官方split_model函数的完整代码见 README.md。它的核心逻辑可以拆成 4 步:
第 1 步:读取 LLM 层数,确定每卡层数
world_size = torch.cuda.device_count() # 可见 GPU 数 num_layers = config.llm_config.num_hidden_layers # 38B 为 64 num_layers_per_gpu = math.ceil(num_layers / (world_size - 0.5))注意分母是world_size - 0.5——第一张卡被当成"半张卡"。因为 ViT 视觉编码器(~12GB)固定放在 GPU 0 上,挤占了大量显存,所以 GPU 0 只能承担约一半的 LLM 层数:
num_layers_per_gpu[0] = math.ceil(num_layers_per_gpu[0] * 0.5)以 3 张 80GB 卡为例:每卡约 64 / 2.5 ≈ 26 层,GPU 0 承担 13 层 + ViT + 首尾层,GPU 1、GPU 2 各承担 26 层,负载大致均衡。
第 2 步:逐层写入 device_map
for i, num_layer in enumerate(num_layers_per_gpu): for j in range(num_layer): device_map[f'language_model.model.layers.{layer_cnt}'] = i layer_cnt += 1生成的是一张"层号 → 卡号"的映射表,例如 3 卡时:
| GPU | 承载模块 |
|---|---|
| GPU 0 | ViT、mlp1、embed_tokens、lm_head、layers 0~12、最后一层 63 |
| GPU 1 | layers 13~38 |
| GPU 2 | layers 39~62 |
第 3 步:ViT 与投影层固定到 GPU 0
device_map['vision_model'] = 0 device_map['mlp1'] = 0图片先进入 GPU 0 的 ViT 做特征提取,再经 MLP 投影送入 LLM 第一层(也在 GPU 0),数据流向最顺,跨卡传输量最小。
第 4 步(关键):首层与尾层同卡
device_map['language_model.model.embed_tokens'] = 0 device_map['language_model.lm_head'] = 0 device_map[f'language_model.model.layers.{num_layers - 1}'] = 0README 对此有明确解释(README.md):这样做是为了避免多 GPU 推理时张量不在同一设备导致的报错——嵌入层产出、最后一层与 lm_head 消耗的张量必须同设备,把首尾层"闭环"到同一张卡上,就不会出现Expected all tensors to be on the same device这类错误。
硬件配置速查:几张卡才够?
README 在 Inference 章节 给出了官方建议:
| 加载方式 | 最低硬件要求 |
|---|---|
load_in_8bit=True(BNB 8-bit 量化) | 2 × 80GB GPU |
load_in_8bit=False(bf16 全精度) | 3 × 80GB GPU |
💡 提示:8-bit 量化会把权重压到约 38GB,两张 80GB 卡分压后仍有充裕空间放 KV Cache;bf16 则三卡起步。
实战:加载模型并跑通推理
以下流程基于 transformers(官方要求transformers>=4.37.2),完整可运行代码在 README.md。
1. 用 split_model 生成 device_map 并加载模型
device_map = split_model('InternVL3-38B') model = AutoModel.from_pretrained( path, torch_dtype=torch.bfloat16, low_cpu_mem_usage=True, use_flash_attn=True, trust_remote_code=True, device_map=device_map).eval()2. 加载图片与对话
pixel_values = load_image('./examples/image1.jpg', max_num=12).to(torch.bfloat16).cuda() generation_config = dict(max_new_tokens=1024, do_sample=True) question = '<image>\nPlease describe the image shortly.' response = model.chat(tokenizer, pixel_values, question, generation_config)仓库自带的 examples/ 目录包含示例图片与视频(如 examples/red-panda.mp4),可直接验证单图对话、多图对比、视频理解等场景。
常见坑与排查清单
| 问题 | 原因与对策 |
|---|---|
tensors not on the same device报错 | 首尾层未同卡。确认device_map中embed_tokens、lm_head与最后一层都指向 GPU 0 |
| GPU 0 显存爆、其他卡空闲 | 忘了 ViT 占 12GB,第一张卡要按"半卡"计算层数,即world_size - 0.5的算法 |
| 卡数不够导致加载失败 | bf16 至少 3 × 80GB;可改用load_in_8bit=True降为 2 × 80GB |
trust_remote_code缺失 | InternVL3 使用自定义建模代码 modeling_internvl_chat.py(配置入口 configuration_internvl_chat.py),加载时必须传trust_remote_code=True |
| 想显式指定某些卡 | 用CUDA_VISIBLE_DEVICES=0,1,2控制可见 GPU,split_model会自动按可见卡数计算 |
进阶:生产部署可换用 LMDeploy
split_model方案适合验证与小规模推理。如果要做高并发服务,官方推荐使用 LMDeploy(见 README.md):
lmdeploy serve api_server OpenGVLab/InternVL3-38B \ --chat-template internvl2_5 --server-port 23333 --tp 2它通过 Tensor Parallelism(--tp 2)实现张量并行,配合 OpenAI 兼容接口,吞吐和稳定性都优于手动切层方案。
总结
InternVL3-38B-Instruct 的多卡部署核心就是三句话:
- 64 层 LLM 逐层切分:
split_model按world_size - 0.5均分层数,生成device_map; - 第一张卡按半卡算:ViT + mlp1 固定在 GPU 0,所以它少分一半 LLM 层;
- 首尾层必须同卡:
embed_tokens、lm_head、最后一层都放 GPU 0,规避跨设备张量报错。
记住这套原理后,无论是 2 卡量化还是 3 卡全精度,你都能自行调整分配策略,把这个 38B 多模态模型稳稳跑起来。
【免费下载链接】InternVL3-38B-Instruct
相关推荐
批量推理提速指南:InternVL3-38B-Instruct batch_chat 批处理实战
批量推理提速指南:InternVL3 38B Instruct batch_chat 批处理实战 InternVL3 38B Instruct 是 OpenGV
原生多模态预训练原理:InternVL3-38B-Instruct 为何文本能力反超 Qwen2.5
原生多模态预训练原理:InternVL3 38B Instruct 为何文本能力反超 Qwen2.5 InternVL3 38B Instruct 是 Open
显存紧张也能跑!InternVL3-38B-Pretrained 8位量化与多卡部署避坑指南
显存紧张也能跑!InternVL3 38B Pretrained 8位量化与多卡部署避坑指南 InternVL3 38B Pretrained 是 Intern
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考