RTX 5090 32GB 单卡复现 Spatial-MLLM 全记录:环境配置、踩坑修复、VSI-Bench 与 SA Sampling 结果对齐

这篇文章记录一下我在 RTX 5090 32GB 上复现 Spatial-MLLM 的完整过程。
重点不是论文解读,而是:官方 README 在 5090 上并不能直接跑,应该怎么修,最后如何把结果复现出来。

如果你也在新卡(尤其是 5090)上跑这篇工作,这篇记录应该能帮你省不少时间。


1. 论文与项目

论文:

Spatial-MLLM: Boosting MLLM Capabilities in Visual-based Spatial Intelligence

项目地址:
https://github.com/diankun-wu/Spatial-MLLM

论文核心目标是增强 MLLM 在视频空间推理上的能力,尤其是:

  • 物体计数
  • 相对方向
  • 相对距离
  • 房间大小估计
  • 路径规划
  • 出现顺序等

README 中已经提供了:

  • 官方 checkpoint
  • inference 脚本
  • VSI-Bench eval 脚本
  • SA sampling 脚本 / 预采样帧

所以从复现角度看,这个项目本来是比较友好的。
真正的坑主要出在 5090 环境兼容性上。


2. 我的环境

我使用的是:

  • GPU:RTX 5090 32GB
  • Driver:580.126.20
  • System CUDA:13.0
  • 操作方式:平时通常只用 1 张卡
  • 本次固定使用:物理 1 号卡

查看方式:

nvidia-smi

我机器上有 4 张 5090,但为了避免占用组内其他卡,后面所有命令统一使用:

CUDA_VISIBLE_DEVICES=1

注意:

  • 这里的 1 指的是物理 1 号卡
  • 程序内部仍然会把它看成 cuda:0

3. 先说最终复现结果

我最终成功复现了两组核心结果:

3.1 Spatial-MLLM-v1.1-Instruct-135K(无 SA Sampling)

我的结果

  • Acc micro: 49.08
  • MRA micro: 52.86
  • All micro: 51.02
  • Acc macro: 46.95
  • MRA macro: 53.85
  • All macro: 50.40

README 官方结果

  • Acc micro: 49.28
  • MRA micro: 52.88
  • All micro: 51.13
  • Acc macro: 47.07
  • MRA macro: 53.88
  • All macro: 50.48

差距

  • Micro All: -0.11
  • Macro All: -0.08

3.2 Spatial-MLLM-v1.1-Instruct-135K + SA Sampling

我的结果

  • Acc micro: 52.01
  • MRA micro: 53.65
  • All micro: 52.85
  • Acc macro: 48.61
  • MRA macro: 55.09
  • All macro: 51.85

README 官方结果

  • Acc micro: 52.13
  • MRA micro: 53.33
  • All micro: 52.75
  • Acc macro: 49.15
  • MRA macro: 54.46
  • All macro: 51.81

差距

  • Micro All: +0.10
  • Macro All: +0.04

3.3 SA Sampling 带来的提升

我的提升

  • Micro All:51.02 -> 52.85,提升 +1.83
  • Macro All:50.40 -> 51.85,提升 +1.45

README 的提升

  • Micro All:51.13 -> 52.75,提升 +1.62
  • Macro All:50.48 -> 51.81,提升 +1.33

这说明:

我不仅复现了基础结果,也复现了 SA Sampling 带来的增益趋势。


4. 最大坑:官方 README 的 torch 在 5090 上跑不起来

README 给出的核心环境是:

  • torch==2.6.0
  • torchvision==0.21.0
  • torchaudio==2.6.0
  • flash_attn==2.7.4.post1
  • CUDA 12.4

我一开始也是照着装的:

conda create -n spatial-mllm python=3.10 -y
conda activate spatial-mllm

pip install torch==2.6.0 torchvision==0.21.0 torchaudio==2.6.0 --index-url https://download.pytorch.org/whl/cu124
pip install transformers==4.51.3
pip install accelerate datasets decord deepspeed einops matplotlib pandas python_Levenshtein qwen_vl_utils ray safetensors tqdm tyro wandb

wget https://github.com/Dao-AILab/flash-attention/releases/download/v2.7.4.post1/flash_attn-2.7.4.post1+cu12torch2.6cxx11abiFALSE-cp310-cp310-linux_x86_64.whl
pip install flash_attn-2.7.4.post1+cu12torch2.6cxx11abiFALSE-cp310-cp310-linux_x86_64.whl

pip list 看起来完全正常。


4.1 但一测 CUDA 就炸了

测试命令:

python - <<'PY'
import torch
print("torch:", torch.__version__)
print("cuda available:", torch.cuda.is_available())
x = torch.randn(2, 3).cuda()
y = torch.randn(2, 3).cuda()
z = x + y
print(z)
PY

报错:

RuntimeError: CUDA error: no kernel image is available for execution on the device

同时还会看到警告:

NVIDIA GeForce RTX 5090 with CUDA capability sm_120 is not compatible with the current PyTorch installation.
The current PyTorch install supports CUDA capabilities sm_50 sm_60 sm_70 sm_75 sm_80 sm_86 sm_90.

4.2 原因

本质原因就是:

官方 README 里的 torch wheel 不支持 RTX 5090 的 sm_120

也就是说:

  • 你可以 import torch
  • 也可以看到 torch.cuda.is_available() == True
  • 但真正执行 CUDA kernel 时会直接炸

这个坑非常隐蔽。


5. 正确做法:升级到支持 5090 的 PyTorch nightly

5.1 卸载旧 torch

pip uninstall -y torch torchvision torchaudio

5.2 安装支持新卡的 nightly 版本

我最终使用的是:

pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128

安装后版本大致是:

  • torch 2.12.0.dev20260330+cu128
  • torchvision 0.27.0.dev20260330+cu128
  • torchaudio 2.11.0.dev20260330+cu128

5.3 验证 torch 是否真正能在 5090 上运行

CUDA_VISIBLE_DEVICES=1 python - <<'PY'
import torch
print("torch:", torch.__version__)
print("cuda available:", torch.cuda.is_available())
print("device count:", torch.cuda.device_count())
print("device 0:", torch.cuda.get_device_name(0))
x = torch.randn(2, 3, device='cuda')
y = torch.randn(2, 3, device='cuda')
z = x + y
print("ok add:", z.device, z)
PY

如果这一步都过不了,后面所有模型推理都别谈。


6. 第二个坑:flash-attn 和新 torch 不兼容

升级 torch 后,再 import flash_attn,会报类似错误:

ImportError: ... flash_attn_2_cuda ... undefined symbol ...

这是典型的 ABI 不兼容。


6.1 处理方式:先卸载 flash-attn

pip uninstall -y flash-attn

这里我的建议很明确:

不要一开始就死磕在 5090 + nightly torch 上重编 flash-attn。

先把模型跑通更重要。


7. 第三个坑:仓库代码里写死了 flash_attention_2

即使你把 flash-attn 卸掉,仓库代码里还是会写:

attn_implementation="flash_attention_2"

这会导致模型加载时报错。


7.1 我修改了两个关键文件

文件 1:src/inference.py

把:

attn_implementation="flash_attention_2"

改成:

attn_implementation="sdpa"

文件 2:src/evaluation/vsibench/eval_vsibench.py

同样把:

attn_implementation="flash_attention_2"

改成:

attn_implementation="sdpa"

7.2 为什么改成 sdpa

因为 sdpa 是 PyTorch 官方实现,
5090 + torch nightly 上更稳。

而且实践证明:

sdpa 仍然可以高度复现 README 结果。

所以这属于兼容性修复,不是方法层面的改动。


8. 最终可用环境总结

我最终跑通的关键组合是:

  • Python 3.10
  • torch 2.12 nightly + cu128
  • transformers 4.51.3
  • qwen-vl-utils
  • decord
  • 不使用 flash-attn
  • attn_implementation="sdpa"

9. 下载模型与数据

9.1 下载 Spatial-MLLM-v1.1-Instruct-135K

我建议先下载 135K,不要一上来就 820K:

mkdir -p checkpoints

hf download Diankun/Spatial-MLLM-v1.1-Instruct-135K \
  --local-dir checkpoints/Spatial-MLLM-v1.1-Instruct-135K

9.2 下载 VSI-Bench

hf download nyu-visionx/VSI-Bench \
  --local-dir datasets/evaluation/vsibench \
  --repo-type dataset

解压:

for f in datasets/evaluation/vsibench/*.zip; do
  unzip "$f" -d datasets/evaluation/vsibench
done

9.3 下载 SA Sampling 官方预采样帧

README 推荐直接用官方预采样帧,我也建议这样做:

hf download Diankun/Spatial-MLLM-Data evaluation/vsibench/sa_sampling_16f.zip \
  --repo-type dataset \
  --local-dir .

解压:

unzip evaluation/vsibench/sa_sampling_16f.zip -d datasets/evaluation/vsibench

10. 先跑单样本 inference

10.1 跑 Spatial-MLLM

CUDA_VISIBLE_DEVICES=1 python src/inference.py \
  --model_path checkpoints/Spatial-MLLM-v1.1-Instruct-135K \
  --model_type spatial-mllm \
  --video-path assets/arkitscenes_41069025.mp4 \
  --text "How many chair(s) are in this room? Please answer the question using a single word or phrase."

我的输出:

Time taken for inference: 2.81 seconds
GPU Memory taken for inference: 13.45 GB
Output: ['2']

10.2 跑 baseline:Qwen2.5-VL-3B

仓库里也支持 baseline:

CUDA_VISIBLE_DEVICES=1 python src/inference.py \
  --model_path Qwen/Qwen2.5-VL-3B-Instruct \
  --model_type qwen2.5-vl \
  --video-path assets/arkitscenes_41069025.mp4 \
  --text "How many chair(s) are in this room? Please answer the question using a single word or phrase."

我的输出:

Time taken for inference: 2.09 seconds
GPU Memory taken for inference: 8.15 GB
Output: ['1']

这一步的意义是:

  • 确认当前环境同时支持 baseline 和 Spatial-MLLM
  • 确认单卡 32GB 足够推理

11. 正式跑 VSI-Bench

11.1 无 SA Sampling

先确认你已经把 eval_vsibench.py 中的 flash_attention_2 改成了 sdpa

然后直接运行:

CUDA_VISIBLE_DEVICES=1 bash scripts/evaluation/evaluate_vsibench_spatial_mllm.sh

这个脚本默认就是:

  • nframes=16
  • batch_size=1
  • 模型路径:checkpoints/Spatial-MLLM-v1.1-Instruct-135K

我这边单卡大概跑了 4 小时左右。


11.2 最终结果

'acc': {'micro': 0.4907630522088353, 'macro': 0.46947505121715705},
'mra': {'micro': 0.5285606066668124, 'macro': 0.5385376053044695},
'all': {'micro': 0.5102144252632329, 'macro': 0.5040063282608133}

换算成百分数:

  • Acc micro: 49.08
  • MRA micro: 52.86
  • All micro: 51.02
  • Acc macro: 46.95
  • MRA macro: 53.85
  • All macro: 50.40

12. 跑 SA Sampling 版本

12.1 确认目录存在

官方预采样帧解压后,目录应类似:

datasets/evaluation/vsibench/sa_sampling_16f/arkitscenes/41069025/...

12.2 运行 SA Sampling 评测

CUDA_VISIBLE_DEVICES=1 bash scripts/evaluation/evaluate_vsibench_spatial_mllm_w_sa_sampling.sh

这个脚本和普通 eval 的主要区别是:

--video_dir "datasets/evaluation/vsibench/sa_sampling_16f"

12.3 最终结果

'acc': {'micro': 0.5200803212851406, 'macro': 0.4860882970391681},
'mra': {'micro': 0.5365151519576709, 'macro': 0.550855950407908},
'all': {'micro': 0.5285380119236357, 'macro': 0.5184721237235381}

换算成百分数:

  • Acc micro: 52.01
  • MRA micro: 53.65
  • All micro: 52.85
  • Acc macro: 48.61
  • MRA macro: 55.09
  • All macro: 51.85

13. 我的结果与 README 对比

13.1 总表

Setting Acc Micro MRA Micro All Micro Acc Macro MRA Macro All Macro
我的 Spatial-MLLM-v1.1-135K 49.08 52.86 51.02 46.95 53.85 50.40
我的 Spatial-MLLM-v1.1-135K + SA 52.01 53.65 52.85 48.61 55.09 51.85
README 135K 49.28 52.88 51.13 47.07 53.88 50.48
README 135K + SA 52.13 53.33 52.75 49.15 54.46 51.81

13.2 SA Sampling 增益对比

对比 Micro All 提升 Macro All 提升
我的 SA Sampling 提升 +1.83 +1.45
README 的 SA Sampling 提升 +1.62 +1.33

14. 32GB 显存够不够?

我的结论是:

对 inference 和 evaluation 来说:够

  • Spatial-MLLM 单样本推理显存约 13.45 GB
  • Qwen2.5-VL-3B baseline 约 8.15 GB
  • 单卡 32GB 足够做 VSI-Bench eval

对训练来说:要另算

如果你后面要做:

  • SFT
  • SA sampling 自采样实验
  • 更大规模模型
  • RL

那就要重新评估。

但至少对这篇工作当前 repo 的:

官方 checkpoint + 官方 inference + 官方 evaluation

32GB 是足够的。


15. 我的复现建议

如果你也要在 5090 上复现,我建议按这个顺序:

Step 1:照 README 装环境

但不要盲信能直接跑。

Step 2:第一时间测 CUDA tensor

不要等模型和数据都下好了才发现 torch 根本不支持 5090。

Step 3:升级到支持 5090 的 torch nightly

这是关键中的关键。

Step 4:卸载 flash-attn

不要先在这个坑里卡半天。

Step 5:把 flash_attention_2 改成 sdpa

至少改:

  • src/inference.py
  • src/evaluation/vsibench/eval_vsibench.py

Step 6:先跑单样本 inference

确认模型、视频、处理器都工作正常。

Step 7:再跑正式 eval

先复现 135K,再复现 135K + SA sampling。


16. 这次复现最核心的经验

我觉得有三点最值得记:

1)新卡上的复现,难点往往不是模型,而是底层环境

尤其是:

  • torch wheel 是否支持新架构
  • flash-attn 是否兼容
  • 仓库是否写死注意力后端

2)先跑通,比先追“最优环境”更重要

我没有先死磕 flash-attn,而是先用 sdpa 跑通,结果证明这是对的。

3)结果趋势比逐点完全一致更重要

但这次更好的是:
我不仅趋势对了,数值也和 README 非常接近。


17. 关键命令汇总

安装支持 5090 的 torch

pip uninstall -y torch torchvision torchaudio
pip install --pre torch torchvision torchaudio --index-url https://download.pytorch.org/whl/nightly/cu128

卸载旧 flash-attn

pip uninstall -y flash-attn

下载模型

hf download Diankun/Spatial-MLLM-v1.1-Instruct-135K \
  --local-dir checkpoints/Spatial-MLLM-v1.1-Instruct-135K

下载 VSI-Bench

hf download nyu-visionx/VSI-Bench \
  --local-dir datasets/evaluation/vsibench \
  --repo-type dataset

for f in datasets/evaluation/vsibench/*.zip; do
  unzip "$f" -d datasets/evaluation/vsibench
done

下载 SA Sampling 预采样帧

hf download Diankun/Spatial-MLLM-Data evaluation/vsibench/sa_sampling_16f.zip \
  --repo-type dataset \
  --local-dir .

unzip evaluation/vsibench/sa_sampling_16f.zip -d datasets/evaluation/vsibench

跑单样本 inference

CUDA_VISIBLE_DEVICES=1 python src/inference.py \
  --model_path checkpoints/Spatial-MLLM-v1.1-Instruct-135K \
  --model_type spatial-mllm \
  --video-path assets/arkitscenes_41069025.mp4 \
  --text "How many chair(s) are in this room? Please answer the question using a single word or phrase."

跑 VSI-Bench

CUDA_VISIBLE_DEVICES=1 bash scripts/evaluation/evaluate_vsibench_spatial_mllm.sh

跑 SA Sampling 版 VSI-Bench

CUDA_VISIBLE_DEVICES=1 bash scripts/evaluation/evaluate_vsibench_spatial_mllm_w_sa_sampling.sh

18. 最后

总的来说,这次复现给我的感受是:

Spatial-MLLM 本身的 inference / eval 流程并不复杂,真正麻烦的是 5090 上的环境兼容。

一旦你把这几件事处理好:

  • torch 升级
  • flash-attn 移除
  • attn_implementation 改成 sdpa

后面的事情就顺了很多。

而且最终结果也证明,这种兼容性修改并没有破坏模型表现。


如果后面我继续跑:

  • Qwen2.5-VL-3B 的完整 VSI-Bench baseline
  • Spatial-MLLM-820K
  • ScanQA
  • 或训练部分

我再继续更新。


Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐