48GB 到底装得下什么
70B 的 Q4_K_M 权重约 40.7GB;加上 4K 的 KV 缓存和激活缓冲,估算约 46GB,而两张卡合计 48GB。这是 96% —— 能加载,但属于"偏紧"区间,不是从容运行,任何一张卡上都没有余量再跑桌面。8K 上下文时同一个模型约 47.5GB。请把 48GB 上跑 70B Q4_K_M 当成无显示器的配置来对待,并且要知道 llama.cpp 的默认设置甚至不会尝试把它整个放上去:它的自动适配会在每张卡上留出 1 GiB,于是还没开始算模型,两张卡的预算就只剩约 46GB。
Llama 3.3 70B Q4_K_M @4K ctx ≈ 46.1 GB of 48 GB amber — loads, no margin
Llama 3.3 70B Q4_K_M @8K ctx ≈ 47.5 GB of 48 GB amber — at the ceiling
Llama 3.3 70B Q3_K_M* @8K ctx ≈ 38.4 GB of 48 GB comfortable
Seed-OSS 36B Q4_K_M @8K ctx ≈ 25.0 GB of 48 GB comfortable
(estimates from this site’s calculator: weights + KV cache + 10% activations)
* generic Q3_K_M rate — this index lists no Q3_K_M build of Llama 3.3 70B前置条件
两张能被驱动识别的 CUDA 卡、一个启用了 CUDA 的 llama.cpp,以及足够在分发过程中读取模型文件的系统内存。开关是 GGML_CUDA=ON。旧名字会被识别而不是被忽略 —— LLAMA_CUDA 仍然有效、只是附带弃用警告,LLAMA_CUBLAS 会让配置步骤直接报错 —— 但拼错的开关只会在配置结束时出现在 "Manually-specified variables were not used" 下面,编出来的是纯 CPU 版本。两张卡不需要 NVLink:默认的按层切分模式下,每张卡承载一段完整的层,跨卡传输的只有分界处的激活值,llama.cpp 的多卡文档也写明这种模式能容忍较慢的互联。
nvidia-smi --query-gpu=index,name,memory.total --format=csv
cmake -B build -DGGML_CUDA=ON -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
./build/bin/llama-server --list-devices # both cards should be listed在两张卡之间切分
这一步依赖的两处 llama.cpp 行为都变了。--tensor-split 现在是可选的:不写的话,按层切分会按每张卡的显存比例分配,两张同型号 3090 本来就是平均切分。写的话,它接受的是比例而不是 GB —— 3,1 表示第一张卡分到 75%。另外 -ngl 默认是 auto,并且 --fit 默认开启:llama.cpp 会调整所有你没有手动设置的内存参数,让模型在每张卡留出 1 GiB 余量的前提下装下,对一个 46GB 的模型来说,这意味着悄悄把一些层放到 CPU 上跑。请显式设置 -ngl all 和 -c,这样装不下的模型会在加载时直接报错,而不是加载成功却很慢。不写 -c 的话,llama.cpp 会从模型训练时的完整上下文开始 —— Llama 3.3 是 128K —— 再由自动适配往下砍。绑定到本机回环地址:llama-server 自己没有任何鉴权。
./build/bin/llama-server \
-m ./models/Llama-3.3-70B-Instruct-Q4_K_M.gguf \
-ngl all -c 4096 \
--host 127.0.0.1 --port 8080
# Mismatched pair (e.g. 24GB + 16GB)? The default split already follows memory;
# override it with proportions only if one card also drives a display:
# --tensor-split 3,2确认两张卡都在承载模型
启动日志会打印卸载到 GPU 的层数;只要不是全部,就说明还有一部分在 CPU 上,无论显卡在做什么,生成速度都会很慢。nvidia-smi 里两张卡应该各自占着大约一半的权重。如果一张卡约 23GB、另一张接近 0,说明第二张卡根本没被用上 —— 检查 --list-devices 的输出和 CUDA_VISIBLE_DEVICES。
# In the startup log:
# load_tensors: offloaded 81/81 layers to GPU
watch -n1 nvidia-smi --query-gpu=index,memory.used --format=csv另一种切分模式
llama.cpp 现在还有 --split-mode tensor:它把每一层都拆到两张卡上,而不是每张卡承载完整的若干层。官方文档把它标为实验性功能,目标是在 NVIDIA 卡上加快生成速度,并且比默认模式更依赖两卡之间的互联。它要求开启 flash attention,不接受量化的 KV 缓存,并且会关掉自动适配,所以上下文要自己定。更早的 row 模式已被弃用。本站没有在两张 3090 上对比过这两种模式和默认模式,因此不给速度结论;如果你要试 tensor 模式,先在自己的机器上和按层切分比较一下每秒 token 数再决定。
当 48GB 装不下这 46GB 时
三种调整,按值得尝试的顺序。降低上下文:只有 KV 缓存随它增长,从 8K 降到 4K 能省出一个多 GB。降一档量化:按计算器的通用 Q3_K_M 比特率,同一个模型在 8K 下约 38.4GB,在两张卡上可以从容运行 —— 不过本索引没有收录 Llama 3.3 70B 的 Q3_K_M 构建,这只是按通用比特率估算的结果,本站也没有它的质量损失数据。或者换一个更小的模型 —— Seed-OSS 36B 在 Q4_K_M、8K 下约 25GB,同样两张卡还能留出余量正常使用机器。加系统内存是没用的:一旦有层溢出到 CPU,这种规模的模型吞吐量会断崖式下跌。
下一步
计算器一次只针对一张卡,所以先用单张 24GB 卡去算 70B,看到的是每张卡承担的那一半,再乘以二 —— 并且把"偏紧"的结论当成真正的警告来看待。
常见问题
两张 RTX 3090 用 llama.cpp 跑 70B 需要 NVLink 吗?
不需要。默认切分模式下每张卡承载一段完整的层,跨卡传输的只有分界处的激活值,llama.cpp 的多卡文档也写明这种模式能容忍较慢的互联。互联速度对实验性的 tensor 切分模式更重要,因为那种模式在每一层内部都要交换数据。
能不能把两张不同的卡配在一起用,比如 RTX 3090 加一张 16GB 的卡?
可以 —— 默认切分本来就按每张卡的显存比例分配,不需要设置 --tensor-split。但 24 + 16 是 40GB,而 70B 的 Q4_K_M 在 4K 下约需 46GB,装不下。按计算器的通用 Q3_K_M 比特率,4K 下约 37.1GB —— 占两张卡的 93%,本站把这算作偏紧,而不是从容运行。
模型明明应该装得下,为什么 llama.cpp 还是把一些层放到了 CPU 上?
因为自动适配默认开启,会在每张卡上留出 1 GiB,而且 -ngl 默认是 auto。所有你没有设置的参数都会被调整到这个余量之内,对一个离上限只差一两 GB 的模型来说,这就意味着不报错、直接把一些层挪到 CPU 上。请传 -ngl all 和明确的 -c,让它要么完整加载到 GPU 上,要么报出一个你能处理的显存不足错误。
这篇指南用到了什么
- 格式
- GGUF
- 对应推荐
- 24GB 能跑的最好的本地大模型
接下来
看看 🟢 RTX 3090 还能跑哪些模型反向查询 —— 24GB、4096 上下文,按质量排序本文涉及的模型
它真的跑起来了吗?
复制命令并不等于它能用,所以站内只在这里问一次。除了你的这个回答之外,不收集任何东西。