BasicSR Windows 编译安装教程 Python3.14 CUDA13.0

系列:Windows AI 开发环境 “没有轮子(.whl) 就自己造”从零到一
难度:⭐⭐⭐⭐
环境:Windows 11 · Python 3.14 · PyTorch 2.12.0.dev+cu130 · CUDA 13.0 · RTX 3090 · VS 2022


前言

XPixelGroup/BasicSR: Open Source Image and Video Restoration Toolbox for Super-resolution, Denoise, Deblurring, etc. Currently, it includes EDSR, RCAN, SRResNet, SRGAN, ESRGAN, EDVR, BasicVSR, SwinIR, ECBSR, etc. Also support StyleGAN2, DFDNet.

basicsr · PyPI

BasicSR/docs/INSTALL.md at master · XPixelGroup/BasicSR

BasicSR 是做超分/图像修复绕不开的库,但它的官方文档只写了 Linux 的安装步骤,Windows 用户在 Python 3.13 + CUDA 13.0 环境下直接 pip install basicsr 大概率翻车——要么找不到 CUDA,要么扩展编译失败,要么在 Python 3.13+ 上直接报 KeyError

本文以实际踩坑过程为主线,记录在 Python 3.14 + CUDA 13.0 + PyTorch nightly 这个"前沿"组合下,完整编译出包含三个 CUDA 扩展的 BasicSR wheel 的完整步骤,以及每一步背后的原理。

BasicSR 的三个 CUDA 扩展:

扩展 用途
deform_conv_ext DCN 可变形卷积,EDVR/BasicVSR 必需
fused_act_ext Fused Leaky ReLU,StyleGAN2 系列必需
upfirdn2d_ext 上采样滤波,StyleGAN2 系列必需

一、环境准备

1.1 本文实际使用的环境

OS       : Windows 11
GPU      : RTX 3090 (sm_86)
Driver   : 595.02
Python   : 3.14.0
PyTorch  : 2.12.0.dev20260323+cu130
CUDA     : 13.0 (Switch-CUDA 多版本管理)
cuDNN    : v9.14 (for CUDA 13.0)
VS       : Visual Studio 2022 Professional v17.12

1.2 CUDA 版本匹配原则

Switch-CUDA 工具来源:

Windows 多版本 CUDA + cuDNN 环境配置完全指南

核心原则:nvcc 版本必须与 PyTorch 内部 CUDA 版本一致。

# 查看 PyTorch 内部 CUDA 版本
python -c "import torch; print(torch.version.cuda)"
# 输出: 13.0

确认是 13.0 后,切换到 CUDA 13.0:

# 加载 Switch-CUDA 工具(若未在 profile 中自动加载)
. D:\Program\switch-cuda.ps1
Switch-CUDA 13.0

# 验证
nvcc --version
# Cuda compilation tools, release 13.0, V13.0.88  ✅

💡 Switch-CUDA 工具:本系列前几期介绍的多版本 CUDA 共存切换脚本,通过读取系统环境变量 cuDNN_PATH_V12_6 ~ cuDNN_PATH_V13_1 动态切换 PATH,支持 CUDA 12.6 ~ 13.1 五个版本一键切换。没有这个工具的读者,手动把对应 CUDA 版本的 binbin\x64 加到 PATH 最前面即可。


二、克隆源码并安装依赖

在 VS 2022 Developer Shell x64 中执行以下所有命令。

# 克隆 BasicSR
git clone https://github.com/XPixelGroup/BasicSR.git
cd BasicSR

# 安装 Python 依赖(不含 CUDA 扩展)
pip install -r requirements.txt


三、设置编译环境变量

Windows 本地编译 CUDA Extension Wheel 完全指南

3.1 subst 消除路径空格

CUDA 安装在 C:\Program Files\...,路径含空格,MSVC 编译时偶发解析错误。用 subst 映射到无空格的盘符:

subst Z: "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v13.0"

3.2 设置所有必要变量

$env:CUDA_HOME             = "Z:"
$env:CUDA_PATH             = "Z:"
$env:CUDA_ROOT             = "Z:"
$env:CudaToolkitDir        = "Z:"
$env:TORCH_CUDA_ARCH_LIST  = "8.6"       # RTX 3090 的 compute capability
$env:MAX_JOBS              = "8"
$env:DISTUTILS_USE_SDK     = "1"
$env:BASICSR_EXT           = "True"      # 告诉 setup.py 编译 CUDA 扩展
$env:PATH                  = "Z:\bin;Z:\bin\x64;" + $env:PATH

⚠️ CUDA 13.x 特别注意:CUDA 13.0 开始 nvcc 同时存在于 bin\bin\x64\,Switch-CUDA 工具已同时将两个路径加入 PATH。手动设置时不要漏掉 bin\x64

3.3 验证 nvcc 优先级

where.exe nvcc
# Z:\bin\nvcc.exe          ← 第一行必须是 subst 后的路径 ✅
# C:\Program Files\...


四、编译 wheel

4.1 第一次尝试:直接 pip wheel

pip wheel . --no-deps -w dist\

报错:

ModuleNotFoundError: No module named 'torch'
ImportError: Unable to import torch - torch is needed to build cuda extensions

原因pip wheel 默认使用 isolated build 环境,该环境是临时创建的,看不到当前 venv 里已安装的 torch。

4.2 改用 --no-build-isolation

正确姿势是用 python -m build 并关闭 isolation:

pip install build   # 先装 build 工具
python -m build --wheel --no-isolation 2>&1 | Tee-Object -FilePath "build.log"

又报错:

KeyError: '__version__'
ERROR Backend subprocess exited when trying to invoke get_requires_for_build_wheel

这才是本文最核心的坑,下一节详细说。


五、核心坑:Python 3.14 的 exec 作用域变化

5.1 问题定位

报错栈指向 setup.py 第 79 行的 get_version() 函数:

def get_version():
    with open(version_file, 'r') as f:
        exec(compile(f.read(), version_file, 'exec'))
    return locals()['__version__']   # ← 问题在这里

5.2 根本原因

Python 3.13+ 对 exec() 的作用域语义做了调整:在函数内部调用不带命名空间参数的 exec(),exec 内部定义的变量不再自动"泄漏"到外层的 locals() 中。

这个变化从 Python 3.13 开始,3.14 完全生效。所有用这个模式读版本号的老项目(setup.pyexec + locals()['__version__'])都会中招,不只是 BasicSR。

5.3 解决方案:patch get_version()

修复方法是给 exec() 传入一个显式的命名空间字典:

# 修复前(Python 3.14 失效)
def get_version():
    with open(version_file, 'r') as f:
        exec(compile(f.read(), version_file, 'exec'))
    return locals()['__version__']

# 修复后(兼容所有 Python 版本)
def get_version():
    ns = {}
    with open(version_file, 'r') as f:
        exec(compile(f.read(), version_file, 'exec'), ns)
    return ns['__version__']

用 Python 一行命令完成 patch(无需手动编辑文件):

python -c "
with open('setup.py', 'r', encoding='utf-8') as f:
    content = f.read()

old = '''def get_version():
    with open(version_file, 'r') as f:
        exec(compile(f.read(), version_file, 'exec'))
    return locals()['__version__']'''

new = '''def get_version():
    ns = {}
    with open(version_file, 'r') as f:
        exec(compile(f.read(), version_file, 'exec'), ns)
    return ns['__version__']'''

content = content.replace(old, new)
with open('setup.py', 'w', encoding='utf-8') as f:
    f.write(content)
print('patch OK')
"

5.4 重新编译

Remove-Item -Recurse -Force build -ErrorAction SilentlyContinue
python -m build --wheel --no-isolation 2>&1 | Tee-Object -FilePath "build.log"

编译成功后可以在输出末尾看到:

adding 'basicsr/ops/dcn/deform_conv_ext.cp314-win_amd64.pyd'       ✅
adding 'basicsr/ops/fused_act/fused_act_ext.cp314-win_amd64.pyd'   ✅
adding 'basicsr/ops/upfirdn2d/upfirdn2d_ext.cp314-win_amd64.pyd'   ✅
Successfully built basicsr-1.4.2-cp314-cp314-win_amd64.whl

三个 .pyd 文件全部编译进 wheel,大功告成。


六、安装与验证

pip install dist\basicsr-1.4.2-cp314-cp314-win_amd64.whl --no-deps

验证所有扩展可正常加载:

from basicsr.ops.dcn import ModulatedDeformConvPack
from basicsr.ops.fused_act import FusedLeakyReLU
from basicsr.ops.upfirdn2d import upfirdn2d
import basicsr
print(f'basicsr {basicsr.__version__} 所有扩展加载成功 ✅')
# basicsr 1.4.2 所有扩展加载成功 ✅


七、踩坑汇总

# 错误信息 原因 解决方案
1 No module named 'torch' pip isolated build 环境隔离了 venv 改用 python -m build --wheel --no-isolation
2 KeyError: '__version__' Python 3.14 改变了 exec() + locals() 的作用域语义 patch get_version(),传入显式命名空间 ns = {}
3 nvcc 版本不匹配 系统默认 CUDA 版本与 PyTorch 内部版本不一致 Switch-CUDA 切换到对应版本
4 路径含空格导致编译错误 MSVC 处理带空格路径不稳定 subst Z: 映射到无空格盘符

八、附:JIT 模式(不想编译 wheel 的替代方案)

如果你不需要打 wheel 分发,只是自用,BasicSR 支持 JIT(Just-In-Time)模式——首次运行时自动编译 CUDA 扩展并缓存,之后直接加载:

# 安装纯 Python 版(不触发 CUDA 扩展编译)
pip install -e . --no-deps

# 运行时开启 JIT
$env:BASICSR_JIT = "True"

# 或写入 venv 的 Activate.ps1,永久生效
Add-Content .venv\Scripts\Activate.ps1 "`n`$env:BASICSR_JIT = 'True'"

JIT 模式的优缺点:

  • 优点:安装简单,无需 VS 编译环境
  • 缺点:首次运行慢(需要编译),需要机器上有 CUDA 开发环境,不适合分发给他人

小结

本文核心结论只有两句话:

  1. python -m build --wheel --no-isolation,不要用 pip wheel,这样才能让 setup.py 看到当前 venv 里的 torch。

  2. Python 3.13+ 的 exec() 不再把变量泄漏到 locals(),凡是用这个老模式读版本号的 setup.py 都要 patch。

这两个坑不只是 BasicSR 独有,整个老一代 PyTorch 扩展生态(BasicSR、mmcv、spconv……)的 setup.py 大量使用相同模式,随着 Python 3.14 普及,会有越来越多的项目踩到第二个坑。希望本文能帮到同样在 Windows 前沿环境折腾的你。


本文为「Windows AI 开发环境从零到一」系列文章,更多 CUDA 编译、多版本管理、ComfyUI 生态相关内容见 CSDN 主页

Logo

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

更多推荐