☰
Windows下AMD显卡跑PyTorch:Pytorch-DirectML部署与实战指南
2026/10/5 3:26:48 网站建设 项目流程

很多朋友手头是AMD显卡,在Windows 10/11上想跑深度学习,第一反应就是上网搜教程,结果搜出来一堆“装WSL2”“换Linux”“上云租GPU”的答案。不是说这些方案不对,而是对一个只想先在本地快速验证模型、跑个YOLO推理、或者做个课程实验的人来说,太重了。我踩过不少坑之后,现在最常用的方案就是Pytorch-DirectML——它能让你在Windows里直接用AMD显卡跑PyTorch,不需要双系统、不需要虚拟机、也不用换卡。这篇文章就专门把这个方案的完整部署过程、验证方法和常见问题讲清楚,照着做就行。

1. 为什么要用Pytorch-DirectML:AMD在Windows下的现实困境

1.1 为什么AMD显卡在Windows下跑深度学习这么费劲

先说一个很多人没搞清楚的背景。PyTorch官方对NVIDIA显卡的支持是走CUDA生态的,CUDA是NVIDIA自己的闭源计算平台,AMD显卡用不了。AMD自己搞了一套ROCm计算平台,性能其实也不错,但官方主打的是Linux系统,Windows版本要么没有、要么是社区魔改版,安装那叫一个折腾。

所以AMD用户在Windows下面临的局面就是:CUDA用不了,ROCm又不给你官方装。于是很多人被迫去装WSL2,在Windows的Linux子系统里跑ROCm,或者在虚拟机里折腾。这当然能解决问题,但环境配置复杂,磁盘占用大,对刚上手的同学非常不友好。

Pytorch-DirectML的出现就是来解决这个尴尬的。它是微软官方维护的一个PyTorch插件,底层走的是DirectX 12里的DirectML接口。DirectX 12是Windows自带的图形API,所有现代显卡、包括AMD、Intel核显、甚至NVIDIA显卡,都很完整地支持。所以通过DirectML,PyTorch就能在Windows上直接调用AMD显卡做计算,不用换系统,也不用碰CUDA。

1.2 DirectML、CUDA、ROCm三者的区别

为了让你对“用了DirectML后到底处于什么水平”有个清晰认知,我做了一个最简单直接的对比表格:

方案支持训练支持推理Windows官方支持安装难度生态完整度
CUDA(NVIDIA)支持支持支持简单最高
ROCm(AMD Linux)支持支持不官方支持较复杂高
ROCm(AMD Windows)支持支持基本没有很折腾低
torch-directml基本可用支持官方支持很简单中
ONNX Runtime DirectML不支持训练支持官方支持简单中

看完这个表你就明白,torch-directml并不是性能最强的方案,但它是“在Windows上最快跑起来”的方案。如果你的需求是:先验证代码能不能跑通、跑个小模型训练、做推理实验,这个方案完全够用。但如果你要微调7B、13B这种大模型,那我还是建议直接租云GPU,别在本地折磨自己。

1.3 torch-directml的能力边界

在开始装之前,得给你打个预防针:torch-directml不是万能的。

它支持PyTorch里大部分常用算子,也支持自动求导,所以训练小型模型是没问题的。但它的算子覆盖度不如CUDA那么全,像某些新出的Transformer层、自定义损失函数、或者一些特殊的数学操作,它可能不支持,会直接报错。另外,torch.compile这种PyTorch 2.0的新特性,在DirectML后端也是不可用的。

还有一个性能问题。DirectML的显存管理和算子融合做得不如CUDA精细,所以在同样一张显卡上,DirectML的实际吞吐可能只有CUDA的一半甚至更低。说句实在话,跑个大点的模型,体感会比较肉。但咱们话说回来,能用就已经解决从0到1的问题了,性能从1到10那是后面慢慢优化的事。

2. 开始之前:驱动、Python环境和版本匹配

2.1 硬件和驱动检查清单

动手安装之前,先把基础条件确认了,别装完环境才发现驱动不对。

第一件事,检查Windows版本。WDDM模式是必须的。你可以按Win+R,输入dxdiag,在弹出的对话框里看“显示”选项卡,里面会列出显卡型号和驱动版本。这里只需要确认一点:Windows 10版本号不低于2004,Windows 11随便什么版本都行。

第二件事,更新AMD显卡驱动。去AMD官网下载Adrenalin版最新驱动,装完以后在任务管理器里看一眼显卡驱动日期,尽量是最近一年之内的。我一再强调驱动,是因为很多人装完torch-directml后报错找不到设备,排查到最后发现是驱动版本太老,DirectML接口根本不认。这种坑,能提前避就提前避。

第三件事,注意核显和独显共存的问题。如果你电脑是AMD核显加AMD独显,或者Intel核显加AMD独显的组合,DirectML会同时识别到两个设备。后面我会讲怎么确认当前用的是哪块卡,这一步千万别跳过,否则你可能辛辛苦苦跑半天,结果全是在核显上跑的,性能比CPU好不了多少。

2.2 创建Python虚拟环境

理论上你直接用系统Python也行,但我强烈建议你用Anaconda或者Miniconda建一个独立环境。为什么?因为深度学习环境里各种包的版本冲突是家常便饭,建独立环境至少能把冲突限定在可控范围。

安装Miniconda的过程就不展开了,装完以后打开Anaconda Prompt,依次执行下面两条命令:

conda create -n dml python=3.10 -y conda activate dml

Python版本强烈建议用3.10。torch-directml官方测试过3.8到3.11,3.10是稳定性最好的中间值。用Python 3.12的话,很多wheel包缺失,你会卡在安装阶段就开始怀疑人生。

2.3 安装PyTorch与torch-directml

进入环境以后,先用国内镜像配置一下pip源,下载速度肉眼可见地提升:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

然后安装PyTorch。注意,这里是关键一步:不要安装带CUDA后缀的版本,哪怕是NVIDIA用户,用DirectML方案也完全不需要CUDA,装上反而会拖慢启动、占用磁盘空间。执行:

pip install torch --index-url https://download.pytorch.org/whl/cpu

这里用官方CPU源,装下来的就是纯CPU版PyTorch,也是后续torch-directml能正常工作的前提条件。接着安装微软的DirectML插件:

pip install torch-directml

装完之后可以看一眼版本:

pip show torch torch-directml

2.4 版本对应关系别搞错

torch-directml和PyTorch之间有严格的版本绑定。要是你随便装了一个新版的torch,再装torch-directml,导入的时候十有八九会报DLL加载错误之类的问题。目前常见的对应关系大概是这样的:

torch-directml版本对应PyTorch版本支持Python版本说明
0.2.x1.13.x3.8-3.11老版本,兼容老项目
0.3.x2.0.x3.8-3.11推荐,算子覆盖更完整
更新版本需要看官方说明需确认版本更新后以官方为准

最稳妥的方式是:先装好torch,再直接pip install torch-directml,它会自动拉取匹配的插件版本。但如果你遇到导入失败,第一反应应该就是版本不匹配,回到这里查一下对应关系。

3. 三步验证:确认GPU真的被PyTorch用起来了

3.1 读取设备信息

装完环境以后,先别急着跑大模型,第一步是验证PyTorch能不能看到AMD显卡。新建一个Python文件,输入以下代码:

import torch import torch_directml as tdml print(tdml.device_count()) print(tdml.device_name(0)) print(tdml.device(0))

device_count()会返回可用GPU数量,device_name(i)则是第i个设备的名称。如果你的电脑只有一张独立显卡,这一行会输出类似“AMD Radeon RX 6600”这样的名称。

如果device_count()返回0,先别慌,大概率是驱动版本问题,或者你正在通过远程桌面连接这台电脑。DirectML在某些情况下依赖本地图形会话,关掉远程桌面,回到物理机上跑一次,经常就好了。

3.2 跑一次矩阵乘法验证

设备识别成功以后,跑一次大的矩阵乘法,这能直观验证GPU计算能力和CPU之间的差距。代码如下:

import torch import torch_directml as tdml import time dml = tdml.device() for name, dev in [("cpu", "cpu"), ("dml", dml)]: a = torch.randn(8192, 8192, device=dev) b = torch.randn(8192, 8192, device=dev) tdml.synchronize() t0 = time.time() c = a @ b tdml.synchronize() print(f"{name}: {time.time() - t0:.4f}s")

这里用了tdml.synchronize()来做同步,因为DirectML的算子调用是异步的,不加同步的话计时会不准。如果你的torch-directml版本没有这个方法,那就多跑几轮取最小值,也能大致判断性能。

正常情况下,DML设备跑8192x8192矩阵乘法,应该比CPU快几倍到几十倍。如果你发现DML和CPU速度差不多,甚至更慢,那很可能你的计算并没有真正跑到独显上——赶紧去看下一节的“GPU占用率检查”。

3.3 观察GPU占用率确认是否真的在算

这个检查很多人会忽略。咱不能光听代码不报错,就认定GPU在干活,尤其是有核显加独显并存的环境。

跑上面那个矩阵乘法的时候,同时打开任务管理器,切到“性能”选项卡,看GPU列表。如果GPU占用率能冲到80%以上,说明真的在计算。如果占用率一直在个位数,或者你发现跑代码的时候是核显在飙升而独显纹丝不动,那就是设备选择出了问题。

怎么解决?很简单,打印出所有设备名称,找到独显对应的编号,然后用tdml.device(编号)手动指定。举个例子,如果你的核显是0号,独显是1号,那初始化设备的时候就写:

dml = tdml.device(1)

这一步非常关键,直接影响你的后续所有代码。别问我怎么知道的——我第一次跑就盯着核显算了半天,浪费了两天时间才发现自己选错设备了。

4. 动手实操:训练一个MNIST分类器,再用YOLOv8跑目标检测

4.1 用DirectML训练一个完整的MNIST模型

验证完设备,我们跑一个真正的训练任务。MNIST手写数字识别可以说是深度学习界的“Hello World”,用全连接网络训练它,既能验证整套环境,又不会花太长时间。

import torch import torch_directml as tdml from torch import nn from torch.utils.data import DataLoader from torchvision import datasets, transforms dml = tdml.device() transform = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,)) ]) train_set = datasets.MNIST(root="./data", train=True, download=True, transform=transform) train_loader = DataLoader(train_set, batch_size=64, shuffle=True, num_workers=2) class Net(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(784, 256) self.fc2 = nn.Linear(256, 128) self.fc3 = nn.Linear(128, 10) self.relu = nn.ReLU() def forward(self, x): x = x.view(x.size(0), -1) x = self.relu(self.fc1(x)) x = self.relu(self.fc2(x)) return self.fc3(x) model = Net().to(dml) optimizer = torch.optim.Adam(model.parameters(), lr=0.001) loss_fn = nn.CrossEntropyLoss() for epoch in range(3): for i, (images, labels) in enumerate(train_loader): images, labels = images.to(dml), labels.to(dml) preds = model(images) loss = loss_fn(preds, labels) optimizer.zero_grad() loss.backward() optimizer.step() if i % 100 == 0: print(f"epoch {epoch}, step {i}, loss {loss.item():.4f}")

几个要点说一下。所有张量都要用.to(dml)搬到GPU上,包括输入图片、标签、模型参数,这一步漏了的话,计算会部分回退到CPU,速度立刻打回原形。第二点,模型尽量用全连接和卷积这些经典结构,这类算子在DirectML上覆盖很齐全,训练过程基本不会报错。第三点,num_workers这个参数在这里是可以正常使用的,适当调大能缓解数据加载瓶颈,但别超过8,Windows上开太多worker反而容易出问题。

在我的一张RX 6600上,跑完3个epoch大约十分钟出头,考虑到MNIST数据量不大,这个速度完全在可接受范围内。

4.2 用YOLOv8做目标检测推理

训练验证完以后,很多人关心的就是实际应用了。YOLO是目标检测领域使用率最高的模型,这里直接用Ultralytics提供的YOLOv8n来演示推理。

先安装Ultralytics:

pip install ultralytics

然后写推理代码:

import torch from ultralytics import YOLO import torch_directml dml = torch_directml.device() model = YOLO("yolov8n.pt") results = model.predict(source="bus.jpg", device=dml) results[0].show()

这里有个兼容性细节值得说一下。不同版本的Ultralytics对device参数的处理有差异,有的版本直接传torch.device对象就行,有的版本需要传字符串。如果你遇到“Invalid device”之类的报错,可以改成先手动把模型搬过去:

model.model.to(dml) results = model.predict(source="bus.jpg")

第一次运行的时候,Ultralytics会自动下载yolov8n.pt权重文件,大概6MB左右,耐心等一会儿就行。推理速度方面,在RX 6600上处理一张普通照片基本在几十毫秒级别,体感和入门级NVIDIA显卡差距不大,日常使用完全够了。

4.3 部署场景:导出ONNX后用DirectML加速

如果你只是想本地验证,上面的步骤已经够用了。但如果是部署到生产环节,我不建议直接拿torch-directml跑,因为它依赖PyTorch整个框架,打包体积大、启动慢。更推荐的做法是:先把PyTorch模型导出成ONNX格式,然后用ONNX Runtime的DirectML执行引擎来跑推理。

导出ONNX的代码很简单:

import torch from ultralytics import YOLO import torch_directml dml = torch_directml.device() model = YOLO("yolov8n.pt") model.model.to(dml) dummy_input = torch.randn(1, 3, 640, 640, device=dml) torch.onnx.export( model.model, dummy_input, "yolov8n.onnx", opset_version=12, input_names=["images"], output_names=["output"] )

导出成功后,安装onnxruntime-directml:

pip install onnxruntime-directml

然后就能用更轻量的方式来做推理。这也是目前很多AI绘画、OCR工具能在Windows上调用AMD显卡加速的底层方案。相比torch-directml,ONNX Runtime DirectML做了更多算子级优化,而且和图形驱动之间的配合更成熟,稳定性也好不少。

5. 我踩过的那些坑:常见报错与性能优化

5.1 设备识别失败的几种情况

用这方案最闹心的就是设备识别不到。我把遇到过的几种情况整理成了下面的速查表:

现象可能原因解决办法
device_count()返回0显卡驱动太老更新到AMD官网最新驱动
device_count()返回0通过远程桌面连接切回物理桌面再测试
device_count()返回0Windows版本过旧升级到Windows 10 2004以上
跑起来独显占用率为0核显独显并存时选错设备打印device_name列表,手动tdml.device(1)
能跑但速度极慢部分算子回退到CPU检查GPU占用率,模型和输入全部放dml设备
import torch_directml报DLL错误torch版本与插件版本不匹配卸载重装,按对应关系装匹配版本

这里最值得强调的还是驱动问题。AMD的驱动更新频率不算快,有时候Windows推送的驱动更新反而会回退版本。如果你确认代码没问题,建议直接去AMD官网手动下载最新驱动,比系统自动更新靠谱得多。

5.2 算子不支持怎么处理

用DirectML跑一些比较新的模型时,偶尔会遇到类似“DML does not support”的报错。看到这个报错不要慌,这基本是算子覆盖问题,有几个常用的处理思路。

第一个思路是换实现方式。举个例子,如果你的自定义Loss里面用了某个不支持的数学函数,可以手写一个等价但用基础算子拼出来的版本。基础的四则运算、指数、对数这些操作,DirectML覆盖得很全。

第二个思路是把不支持的部分留在CPU上算。虽然性能差点,但至少能跑。你得把整个流程拆开,模型的主体放在dml设备上,只在特定的某个步骤把张量搬回CPU,算出结果再搬到GPU继续。

第三个思路也很实际:换一个兼容性更好的模型结构。你在GitHub上看到有些新算法模型,作者只在NVIDIA显卡上测试过,完全没考虑别的后端。这种模型在DirectML上报错非常正常,要么等社区适配,要么换个经典模型用。

最后,定期更新torch-directml。微软还在持续维护这个插件,新版会补不少算子支持。升级之前建议先看看PyPI上的更新日志,不用每次更新都追,但隔半年升一次还是有必要的。

5.3 性能提不上去的排查思路

好多人在本地跑通了环境,但对速度不满意,跑来问我说DirectML是不是就这个水平。说实话,性能瓶颈很多时候不是DirectML本身的问题,而是数据搬移和程序结构造成的。

第一个非常常见的问题是数据每轮都在CPU和GPU之间来回搬。比如训练循环里每次都把图片先搬到GPU,算完loss又搬到CPU,再搬回去。这种频繁的同步会严重拖慢速度。正确做法是让整个计算链条都留在GPU上,尽量避免中途用.item()把数值取回Python端,打印loss这种操作只有在调试时才做。

第二个问题是数据加载跟不上。GPU算得太快,CPU准备数据忙不过来,GPU就在那干等。解决方法是把DataLoader的num_workers调大,并且设置pin_memory=True。虽然pinned memory在DirectML上不是所有场景都有效,但开了一般不会更差。

第三个问题是你可能在毫不知情下使用了CPU回退。有个简单办法:跑推理的时候保持GPU占用率监控窗口打开,如果GPU占用率一直在10%以下徘徊,说明大部分算子在CPU上执行,检查一下代码里是不是有变量忘加.to(dml)。

还有个容易忽略的点是混合精度。DirectML对自动混合精度的支持不完整,不建议用torch.cuda.amp。虽然理论上低精度能加速,但在DirectML后端强行用半精度训练,大概率会收获一堆报错。老老实实用float32跑,省心得多。

从我自己的实际体验来说,Pytorch-DirectML这套方案最适合的使用场景就是:想在Windows下低成本验证深度学习代码、跑课程作业、做做目标检测推理实验。它的安装复杂度比WSL2低一个量级,日常使用的稳定性也足够。如果你后续确定要在本地深度学习这条路上长期走下去,再考虑Linux加ROCm那套方案不迟。至少现在,它已经帮我把AMD这张卡在Windows下真正的价值发挥出来了。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询