如果你也拿到了一台 RTX A4000,准备跑 glm-4v-9b,却在环境配置阶段卡了一整天,那这篇就是写给你看的。我在实际部署时遇到的坑非常典型:系统里已经装了 CUDA 12.4,PyTorch 默认装下来是 cu124 的 wheel,结果一加载模型就报 bitsandbytes CUDA Setup failed;换版本装了 bitsandbytes 0.43.x,又开始报 libcudart 找不到;折腾到最后发现根本不是硬件问题,而是驱动、CUDA Toolkit、PyTorch、bitsandbytes 四者之间的版本矩阵没对齐。
这篇文章我从 RTX A4000 实测出发,完整还原了 glm-4v-9b 环境配置的全过程,重点拆解两块:CUDA 版本冲突是怎么产生的、怎么通过多版本共存解决;bitsandbytes 各类异常背后的真实原因和排查链路。适合手里正好有 A4000/A5000/3060 这类 Ampere 架构显卡、准备跑多模态模型或者做量化的朋友参考。直接把最后验证可用的组合给你,也把每一步为什么这样做讲清楚,尽量让你不用再自己搜一遍热搜里那些零散的报错。
1. 为什么glm-4v-9b的环境总是装不干净:先看清依赖链路的真相
很多人一上来就 pip install transformers torch,然后开始拉模型,报错了才回头查环境。这种顺序在普通模型上可能忍忍就过去了,但在 glm-4v-9b 上基本必炸。原因在于这个模型同时踩中了三个“版本敏感”的组件:transformers 的 trust_remote_code 加载逻辑、CUDA 运行时的链接方式、以及 bitsandbytes 的量化库。
1.1 glm-4v-9b依赖的四个关键组件
glm-4v-9b 是智谱 AI 开源的多模态大模型,参数量约 94 亿,视觉部分用 ViT 编码图像,语言部分基于 GLM-4-9B。它本身不是一个“pip 装上就能跑”的独立软件,而是通过 transformers 的 AutoModelForCausalLM 配合 trust_remote_code=True 动态加载远端代码来使用的。这意味着 transformers 版本和模型代码仓库里的实现必须兼容,否则你会在加载阶段直接看到类似AttributeError: 'ChatGLM4VForCausalLM' object has no attribute 'chat'这种诡异报错。
真正依赖的核心组件有四个:
- PyTorch:模型推理的底层张量框架,它决定了你是否能用 GPU 跑,也决定了你后续所有 CUDA 扩展是否能被找到。
- transformers:模型加载器,glm-4v-9b 官方 demo 使用 4.46.x 等版本验证过,太老或太新都可能出问题。
- bitsandbytes:4bit/8bit 量化库,用来把模型压到小显存里。因为 RTX A4000 只有 16GB 显存,bf16 精度下 glm-4v-9b 光权重就要约 18GB,不量化根本塞不进去。
- CUDA 相关库:驱动、Toolkit、以及 PyTorch wheel 里自带的 CUDA 运行时。这一层最常见的问题是“看起来装了 CUDA,但程序找不到”。
这四者之间不是孤立的,而是一条依赖链:硬件 → 驱动 → CUDA 运行时 → PyTorch → bitsandbytes → 模型代码。链条上任何一环断掉,表现出来就是环境配置失败,但报错往往发生在最末端——比如模型加载时才告诉你量化库挂了。
1.2 三层兼容性:驱动、Toolkit、PyTorch wheel 的不变量
我习惯把 CUDA 生态拆成三层来看,新手最容易混淆的就是这三层。
最底层是GPU 驱动(NVIDIA driver)。它负责和硬件通信,驱动会声明自己“最大支持到 CUDA 12.4”或“CUDA 12.5”,这个数值本质上代表驱动内置的运行时接口能兼容的 CUDA 版本上限。注意,驱动是向下兼容的:新驱动可以跑旧版 CUDA 程序,但旧驱动跑不了新版 CUDA 程序。
中间层是CUDA Toolkit。这是开发编译期工具集,包括 nvcc 编译器、cuBLAS、cuDNN 等。你在系统里通过.run文件安装的,或者通过 conda 安装的 cudatoolkit,都属于这一层。
最上层是PyTorch 预编译 wheel。比如你执行pip install torch==2.1.0 --index-url https://download.pytorch.org/whl/cu121,装回来的 PyTorch 本身已经内置了对应 CUDA 12.1 的运行库,比如 libcudart.so、libcublas.so。换句话说,只要驱动支持 CUDA 12.1,即使你系统里完全没有安装 CUDA Toolkit 12.1,PyTorch 也能正常跑 GPU 运算。
问题在于bitsandbytes 不是纯 Python 库。它包含编译好的.so文件,比如libbitsandbytes_cuda121.so,这个文件在加载时需要找到 CUDA 运行库。它找库的顺序包括系统路径、LD_LIBRARY_PATH、以及 PyTorch 安装目录中的 CUDA 库。任何一环找不到,就会报出后来你看到的那句经典台词:CUDA Setup failed despite GPU being available。
所以你可以这样理解:驱动是操作系统和 GPU 之间的“翻译官”,CUDA Toolkit 是“编译器”,PyTorch wheel 是“运行时依赖打包器”,bitsandbytes 是“外挂插件”。翻译官版本低了,编译器编译出来的插件就跑不动;插件和运行时的 CUDA 版本对不上,也会直接拒绝加载。
1.3 为什么“按文档装”还是失败
我见过太多人在部署 glm-4v-9b 时,第一步就犯了错:直接pip install torch。此时默认装的是带 CUDA 支持的 PyTorch 吗?不一定。如果你在 PyPI 官网源直接装,默认可能装到 CPU 版本,或者装到与你当前驱动不匹配的更高 CUDA 版本。
再加上 A4000 这台机器往往不是专门的深度学习服务器,上面可能已经装了某个旧版 CUDA Toolkit 给其他软件用。你新开一个 Python 环境,nvcc -V显示的可能是旧版本,但 PyTorch wheel 里跑的是新版本;bitsandbytes 里链接的又是另一个版本。三套版本号交叉错位,最终结果就是“torch.cuda.is_available() 返回 True,但加载量化模型时却报错”。这不是运气差,而是链路太长、版本组合没有锁死。
2. RTX A4000上CUDA版本的选型逻辑:驱动、Toolkit与PyTorch的三角关系
我这次实测使用的是一张 RTX A4000,这是 NVIDIA 的 Ampere 架构专业卡,GA104 核心,6144 个 CUDA 核心,16GB GDDR6 显存,计算能力(compute capability)是 sm_86。这决定了它能跑的 CUDA 版本和多数消费级显卡不太一样:它最高可以支持 CUDA 12.4+,不像那些老旧的 Pascal 卡只能停留在 CUDA 11.x。
2.1 先看硬件算力:sm_86 与 bitsandbytes 的兼容边界
选 CUDA 版本前,一定要先搞清楚显卡的计算能力。RTX A4000 是 sm_86,同架构的消费卡是 RTX 3060、3060 Ti;而 RTX 4060、4060 Ti 是 Ada 架构,计算能力是 sm_89;更老的 GTX 10 系是 sm_61,20 系是 sm_75,30 系前中期是 sm_86,40 系是 sm_89。
bitsandbytes 的预编译 wheel 里,不同版本对计算能力的覆盖范围是不一样的。旧版本(比如 0.39.x)只覆盖到 sm_75、sm_80 等几个里程碑架构;新版本(0.43.0 以后)对 sm_86、sm_89 的支持才算比较完善。所以当你把 glm-4v-9b 跑在 A4000 上时,bitsandbytes 的版本必须至少在 0.41 以上,最好直接上 0.43.x。
有些人可能会想:那是不是直接装最新的 CUDA 12.4 + 最新 bitsandbytes + 最新 PyTorch 就万事大吉?实测并非如此。bitsandbytes 0.44.x 虽然支持 CUDA 12.4,但在某些环境下和 PyTorch 2.4+ 的组合会出现新的兼容问题,而对 glm-4v-9b 推理来说,你根本用不到那么新的 CUDA 特性。与其追新,不如选一个经过大量用户验证的稳定组合。
2.2 PyTorch wheel 的 CUDA 版本决定了你的“现实约束”
我在选型时的核心原则是:先定 PyTorch,再反推 CUDA。因为 PyTorch 官方对每个版本提供若干预编译的 CUDA 变体,比如 cu118、cu121、cu124。这些变体决定了你在 pip 安装时的 index-url 后缀。如果选 cu124,那就意味着你的驱动必须至少支持 CUDA 12.4;如果选 cu121,驱动只要支持 CUDA 12.1 即可,这通常没有问题。
在 RTX A4000 上,我最推荐的稳定组合是:
| 组件 | 推荐版本 | 说明 |
|---|---|---|
| NVIDIA 驱动 | 550.120 或更新 | 支持 CUDA 12.4/12.5,向下兼容 12.1 |
| CUDA Toolkit | 12.1(runfile 或 conda) | 不需要装到系统全局,conda 内即可 |
| PyTorch | 2.1.0 或 2.2.0 | 对应--index-url .../whl/cu121 |
| bitsandbytes | 0.43.3 | 对 Ampere 架构和 CUDA 12.1 支持最稳 |
| transformers | 4.46.3 | 对 glm-4v-9b 的 chat 接口兼容 |
| accelerate | 1.0.1 | device_map="auto" 时需要 |
这套组合在 A4000 上实测可以做到:4bit 量化加载 glm-4v-9b 约 6.5GB 显存,推理速度尚可,基本不会遇到奇怪的加载报错。如果你非要用 CUDA 12.4,也能跑通,但 bitsandbytes 建议升到 0.44.1,transformers 也要跟着调,整体变量更多,排查成本更高。
2.3 三种版本矩阵对比:保守、平衡、激进
我整理了三种可用的版本矩阵,方便不同需求的读者直接选一列:
保守组合(新手首选)
- CUDA Toolkit 11.8,PyTorch 2.0.1 + cu118,bitsandbytes 0.41.3
- 优点:资料多、遇到问题随便一搜就有解
- 缺点:对较新的显卡和较新的模型代码支持略弱,如果驱动太新可能跑不了老 wheel
平衡组合(本文实测)
- CUDA Toolkit 12.1,PyTorch 2.1.0 + cu121,bitsandbytes 0.43.3
- 优点:覆盖绝大多数 Ampere/Ada 卡,对 4bit 量化支持成熟
- 缺点:需要手动指定 cu121 的 index-url,不能偷懒直接 pip install torch
激进组合(尝鲜向)
- CUDA Toolkit 12.4,PyTorch 2.4.0 + cu124,bitsandbytes 0.44.1
- 优点:新特性多,服务化框架(如 SGLang)要求的 CUDA 12.4 环境可顺带满足
- 缺点:坑相对多,对 glm-4v-9b 这种“吃老 API”的模型不友好
我的建议是:如果你只是想早日把 glm-4v-9b 跑起来、拿到多模态推理结果,用第二列。如果你后面还要接 vLLM 或 SGLang 做服务化,那就要仔细规划系统级 CUDA 版本,可能需要在系统里维护多套 CUDA,这时第二列的平衡组合依然可以作为 Python 层的主环境,而系统级单独装一个 12.4 给 vLLM 用。
3. CUDA安装实战:多版本共存、run文件报错与nvcc版本不一致排查
定了版本矩阵,接下来就是实操。这一部分最容易翻车的不是命令本身,而是“你以为你装好了,但其实没生效”。
3.1 多版本CUDA共存:conda隔离与系统级切换的取舍
如果你只是为 glm-4v-9b 配置环境,没必要在系统里全局更新 CUDA,更没必要卸掉旧版本。我给两个方案:
方案 A:纯 conda 隔离(本次推荐)
conda create -n glm4v python=3.10 conda activate glm4v conda install -c nvidia cudatoolkit=12.1这条命令会在当前 conda 环境内装一套完整 CUDA 12.1 运行库,不会影响系统全局。之后你在该环境里编译或者运行与 CUDA 12.1 相关的程序,只需要把$CONDA_PREFIX/lib加进LD_LIBRARY_PATH即可。
方案 B:系统级多版本共存
如果你还有其他项目需要 CUDA 11.8,系统里又想保留 12.1,可以分别用.run文件安装到不同目录:/usr/local/cuda-11.8和/usr/local/cuda-12.1,然后通过修改 PATH 和 LD_LIBRARY_PATH 切换默认版本。
export PATH=/usr/local/cuda-12.1/bin:$PATH export LD_LIBRARY_PATH=/usr/local/cuda-12.1/lib64:$LD_LIBRARY_PATH这样做的优点是更接近“系统级开发”的标准姿势,编译环境稳定;缺点是容易把自己绕晕,尤其是当你开了新终端却忘了 source 环境变量时,很可能编译出来的扩展链接到了另一个 CUDA 版本,产生“编译成功但加载失败”的隐患。
3.2 为什么 nvidia-smi 和 nvcc -V 显示的版本不一样
这个现象几乎每个人都会遇到,第一次见的人都会以为系统坏了。实际上,nvidia-smi显示的是当前驱动支持的最大 CUDA 版本(例如 12.4),而nvcc -V显示的是当前 shell 里 PATH 指向的CUDA Toolkit 版本(例如 12.1)。两者本来就不必一致,也不需要一致。
举个例子:驱动版本是 550.120,它支持最高 CUDA 12.4,但你可以同时安装 CUDA Toolkit 12.1 和 11.8,只要它们各自的版本号都低于驱动的上限就能运行。这一点在排查问题时非常关键:你看到 nvidia-smi 显示 12.4,不代表你必须用 cu124 的 PyTorch;你看到 nvcc -V 显示 12.1,也不代表 Python 里的 torch 就一定是 cu121。真正决定 PyTorch 行为的,是 wheel 里自带的 CUDA 运行时版本,而不是系统命令行里喊出的那个版本号。
想快速确认当前 Python 环境里 PyTorch 实际链接的 CUDA 版本,用这行:
import torch print(torch.version.cuda) print(torch.cuda.get_device_name(0)) print(torch.cuda.get_device_capability(0))如果torch.version.cuda是 '12.1',而机器驱动只支持到 12.0,那抱歉,torch 必然加载不了 GPU;反过来,驱动支持 12.4,而 torch.version.cuda 是 '11.8',除非你手动配了旧库路径,否则通常也能正常运行。
3.3 run文件安装CUDA时最常见的报错:gzip invalid compressed data
如果你决定用.run方式在 Ubuntu 上安装 CUDA Toolkit,可能遇到这样一个报错:
sudo sh cuda_12.1.0_530.30.02_linux.run ./cuda_12.1.0_530.30.02_linux.run: 1: ./cuda_12.1.0_530.30.02_linux.run: gzip: stdin: invalid compressed>ls -l cuda_12.1.0_530.30.02_linux.run sha256sum cuda_12.1.0_530.30.02_linux.run然后去 NVIDIA 官网对应版本的页面找到 SHA256 校验值,比对后如果不一致,果断重新下载。重新下载时建议用wget -c断点续传,或者换一个浏览器直接下载,不要用第三方下载器的多线程模式,那种模式对 HTTPS 大文件检测不完全,很容易攒出一个“假文件”。
如果文件校验没问题但依然报 gzip 错误,还有一种可能:你的系统缺少 zlib 相关组件,不过这种情况很少见,新装系统上可以先apt-get install -y zlib1g再试。
我的建议是:如果不是为了编译一些强制依赖系统级 CUDA 的原生扩展,尽量用 conda 方案代替.run安装,省掉能气死人的文件损坏坑。
4. bitsandbytes从报错到跑通:CUDA Setup failed的完整排查链路
glm-4v-9b 环境配置的第二个大坑集中在 bitsandbytes。这个库负责把模型权重量化到 4bit,是整个部署流程中最容易爆雷的组件,而且报错信息往往很有迷惑性:明明torch.cuda.is_available()是 True,GPU 内存也正常,但加载量化模型时就是失败。
4.1 先对照报错清单,再看你的错误属于哪一类
我把实测中遇到和听朋友说过的常见报错整理成一张表,先帮你快速定位:
| 报错信息 | 根本原因 | 快速方针 |
|---|---|---|
CUDA Setup failed despite GPU being available | bitsandbytes 找不到合适的 CUDA 运行库,或预编译的 .so 与当前 CUDA 版本不匹配 | 检查 CUDA_HOME / LD_LIBRARY_PATH,切换 bnb 版本 |
The installed version of bitsandbytes was compiled without GPU support | 安装到了 CPU 版本的 bitsandbytes(常见于 Windows 或旧版本) | 换成 Linux 环境,或升级 bnb 到 0.43+ |
RuntimeError: CUDA error: no kernel image is available for execution on the device | 当前 bnb 的预编译内核不支持 sm_86/sm_89 架构 | 升级 bnb 到 0.43.x,或源码编译 |
ModuleNotFoundError: No module named 'bitsandbytes' | 压根没装 | pip install bitsandbytes |
import bitsandbytes as bnb时直接段错误 | 驱动太老,或 bnb 试图加载不兼容的 CUDA 动态库 | 先更新驱动,再对齐 CUDA 运行库 |
很多人的情况是第一类“CUDA Setup failed despite GPU being available”,这也是本文要重点讲的。这句话翻译成人话就是:bitsandbytes 已经加载了,但它在系统里找不到可以用的 CUDA 动态库,或者找到的库版本和它编译时依赖的不一致。
4.2 排查链路:CUDA_HOME、LD_LIBRARY_PATH和编译期链接的关系
先看一个最简单的验证脚本:
import torch import bitsandbytes as bnb print("torch.cuda.is_available:", torch.cuda.is_available()) print("bnb version:", bnb.__version__)如果你得到:
torch.cuda.is_available: True bnb version: 0.43.3然后执行量化操作时依然报CUDA Setup failed,那问题大概率出在“bnb 找库路径”上。
bitsandbytes 在 Linux 下定位 CUDA 库的顺序大致是:先从LD_LIBRARY_PATH查找,再从系统默认目录查找,最后尝试从 torch 安装目录中寻找。如果它找到了一个版本不对的libcudart.so,就会直接失败。最常见的两个故障原因:
- 没有设置
LD_LIBRARY_PATH,而系统默认的/usr/local/cuda/lib64里只有一个不匹配的旧版本。 LD_LIBRARY_PATH里混入了多个 CUDA 版本的库目录,优先级最高的那个碰巧是错的。
解决办法也简单,在 conda 环境下执行:
conda activate glm4v export LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH然后再跑一次验证脚本。如果你用的是 conda 安装的 cudatoolkit,它的 lib 目录就在$CONDA_PREFIX/lib下。这套操作相当于给程序指路:你要找的 libcudart.so 在这里,别去系统里翻乱碰运气了。
如果设置了之后依然失败,那就再检查一下你到底有没有把 cudatoolkit 装进当前环境:
conda list | grep cudatoolkit建议输出里能看到cudatoolkit 12.1字样。如果什么都没有,那就老老实实执行:
conda install -c nvidia cudatoolkit=12.1还有一种更“轻”的替代方案,不需要装整个 cudatoolkit,只装 NVIDIA 提供的 CUDA 运行时组件:
pip install nvidia-cuda-runtime-cu12这个包只包含运行库,不包含 nvcc 编译器,对纯推理场景足够了。但如果你之后还要手动编译 CUDA 扩展,还是建议装完整的 cudatoolkit。
4.3 为什么 torch 能用但 bitsandbytes 不能用
很多人卡在这一点想不通:PyTorch 都能正常跑 GPU 了,为什么一个依赖 torch 的库反而不行?这里要科普一个底层区别:PyTorch 在加载时,会把 wheel 自带的 CUDA 库路径打包进自己的运行时,所以它不依赖系统LD_LIBRARY_PATH也能找到自己的 libcudart。而 bitsandbytes 是独立于 PyTorch 动态加载的,需要系统动态链接器去搜索库路径,所以对系统的库路径设置敏感得多。
打个比方,PyTorch 是个自带“外卖”的人,它在自己的包里就装好了所有要用的饭;而 bitsandbytes 是个要“出门觅食”的人,得靠系统路径这本地图才能找到餐厅。地图标注错了,它就只能饿肚子报错。
如果你不想手动每个终端都设置LD_LIBRARY_PATH,可以在激活 conda 环境后执行:
conda env config vars set LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH conda deactivate && conda activate glm4v这样每次激活 glm4v 环境时,LD_LIBRARY_PATH都会自动带上环境内的库目录,省去重复导出。
4.4 兜底方案:手动源码编译bitsandbytes
当预编译 wheel 在当前环境无论如何都用不了时,手动编译是最后一道防线。这个方法也适合你有特殊架构需求、或者需要自定义 CUDA 扩展的场景。
git clone https://github.com/TimDettmers/bitsandbytes.git cd bitsandbytes conda activate glm4v pip install -e .在编译前,确保nvidia-smi显示的驱动版本高于你选定的 CUDA Toolkit 版本,并且nvcc -V能正常输出。如果你在 conda 环境里通过了cudatoolkit=12.1,那 nvcc 可能仍然需要用系统里的 CUDA Toolkit 来提供,也可以额外安装cudatoolkit-dev来获得 nvcc:
conda install -c nvidia cudatoolkit-dev=12.1编译过程一般需要几分钟,期间能看到 CMake 自动检测显卡架构。如果检测不到或者你想手动指定,可以设置:
export CMAKE_CUDA_COMPILER=/usr/local/cuda/bin/nvcc export TORCH_CUDA_ARCH_LIST="8.6" pip install -e .这里的8.6对应的就是 RTX A4000 的 sm_86。编译完成后,再跑之前的验证脚本,一般就能顺利通过。
5. 最后把一切串起来:RTX A4000上加载与推理实测
环境配置的苦吃完了,总算到了真正跑模型的时刻。这一节我给出完整可复现的命令序列和代码,基于前文推荐的平衡组合:Python 3.10 + CUDA 12.1 + PyTorch 2.1.0(cu121)+ bitsandbytes 0.43.3 + transformers 4.46.3。
5.1 从零到一:一条龙创建干净环境
不要在你现有的 AI 环境里直接装,也不要图省事覆盖系统 Python。多模态模型的依赖版本非常敏感,一个独立 conda 环境能帮你隔离掉大量历史包袱。
conda create -n glm4v python=3.10 -y conda activate glm4v conda install -c nvidia cudatoolkit=12.1 -y pip install torch==2.1.0 --index-url https://download.pytorch.org/whl/cu121 pip install transformers==4.46.3 accelerate==1.0.1 sentencepiece Pillow pip install bitsandbytes==0.43.3 conda env config vars set LD_LIBRARY_PATH=$CONDA_PREFIX/lib:$LD_LIBRARY_PATH conda deactivate && conda activate glm4v装完之后先跑一遍环境体检,确认四件事:PyTorch 能用 GPU、CUDA 版本是 12.1、bitsandbytes 能导入、显存可以正常申请释放。
import torch import bitsandbytes as bnb print("torch:", torch.__version__) print("cuda:", torch.version.cuda) print("gpu:", torch.cuda.get_device_name(0)) print("bnb:", bnb.__version__) t = torch.randn(1000, 1000, device="cuda") print("gpu tensor ok:", t.sum().item())如果这一步没有任何报错,环境基本就稳了。只要有一步报错,回到前面章节按排查链路走,不要急着拉模型。
5.2 加载glm-4v-9b的完整代码
模型权重建议从可用的公开模型托管平台下载。你可以直接使用 Hugging Face 上的THUDM/glm-4v-9b,也可以从国内直接访问的 ModelScope 拉取,下载后指定本地路径加载,避免每次启动都走网络。
import torch from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig from PIL import Image model_path = "THUDM/glm-4v-9b" # 或者你的本地权重路径 quantization_config = BitsAndBytesConfig( load_in_4bit=True, bnb_4bit_compute_dtype=torch.bfloat16, bnb_4bit_quant_type="nf4", bnb_4bit_use_double_quant=True ) tokenizer = AutoTokenizer.from_pretrained(model_path, trust_remote_code=True) model = AutoModelForCausalLM.from_pretrained( model_path, trust_remote_code=True, quantization_config=quantization_config, device_map="auto", torch_dtype=torch.bfloat16 ) image = Image.open("test.png").convert("RGB") query = "请描述这张图片的内容" history = [] result, history = model.chat(tokenizer, query=query, history=history, image=image) print(result)几个细节值得注意:
trust_remote_code=True是必须的,glm-4v-9b 的自定义模型代码不是 transformers 官方内置的,需要动态加载仓库里的 Python 文件。device_map="auto"配合量化配置使用,能自动把部分层分配到不同设备。如果你显存已经很紧张,可以再加max_memory={0: "14GiB"}控制每个设备的使用上限。- 第一次运行会自动可能缓存一些模型文件,耗时较长,耐心等待。
实测在 RTX A4000 上,4bit 量化加载后显存占用大约 6.5GB 到 8GB 左右,给 batch 推理和输入图像留了足够余量。如果你坚持用 bf16 不量化,会在加载阶段直接 OOM,那是把 16GB 显存往绝路上逼。
5.3 遇到OOM或加载慢时的调整策略
如果你在加载模型时看到CUDA out of memory,或者显存不够跑 batch,优先检查这几项:
- 确认量化生效:打印一下模型里的某个 Linear 层,看它是不是
bnb.nn.Params4bit类型。如果还是原来的torch.nn.Linear,说明量化配置没有真正生效,大概率是 transformers 和 bitsandbytes 版本没对齐。 - 调低图像分辨率:glm-4v-9b 内置会将图像缩放、分块,较大的输入图会占用较多显存,可以先用小于 1MB 的测试图跑通流程。
- 限制生成长度:
model.chat内部默认 max_new_tokens 可能较大,可以传入max_new_tokens=256、max_length=512等参数来减少 KV Cache 占用。 - 不要同时开多个会话:单卡 16GB,跑 4bit 量化后的 glm-4v-9b 虽然富余,但开多个 Python 进程同时推理还是容易爆显存。
5.4 如果是Windows系统,你要多注意一件事
RTX A4000 的机器未必一定是 Linux,也有不少人是在 Windows 上做开发。bitsandbytes 在 Windows 上的支持比 Linux 差很多:老版本没有 Windows 预编译 wheel,新版本即便支持,也可能要求特定 MSVC 运行库和 CUDA 版本。
如果你必须在 Windows 上跑,我的建议是优先尝试:
pip install bitsandbytes==0.43.3然后在 Python 里直接 import 测试。如果报“编译时没有 GPU 支持”,大概率是你的 Python/驱动版本不匹配,这时不要硬磕,优先考虑用 WSL2 或者 Docker 跑一个带 CUDA 的 Linux 容器,效率远高于在 Windows 原生环境里折腾源码编译。
我个人的看法是:glm-4v-9b 本身对 Windows 用户不算友好,能上 Linux 就上 Linux。WSL2 里安装 CUDA 之后再跑这套流程,体验会平滑很多。
最后的实操体会
这次在 RTX A4000 上配置 glm-4v-9b,折腾下来我最大的感悟是:环境配置的问题,90% 是版本矩阵不清晰造成的。很多人以为报错是“某个库坏了”,其实背后是驱动、CUDA Toolkit、PyTorch wheel、bitsandbytes 四者在互相对暗号,任何一个对不上,报错就会以最不直观的方式弹出来。
如果你看完这篇还要自己装,我建议你按照这个顺序来:先确认nvidia-smi里的驱动支持版本,再定 PyTorch 的 cu 后缀,然后选配套的 bitsandbytes 版本,最后用 conda 环境把 cudatoolkit 锁在同一版本。不要跳步,不要图省事直接 pip install torch 完事。等你亲自动手走完一遍,再看那些热搜里的“CUDA Setup failed”“invalid compressed data”,就不会再觉得是无头案了。以后再配其他大模型环境,你也能很快判断出问题出在链路哪一环。