在Windows上使用PyTorch训练模型时,任务管理器里的GPU占用率比较低,这是正常的。可以使用nvidia-smi查看真实的GPU占用率。
任务管理器里的GPU占用率
使用nvidia-smi查看真实的GPU占用率
命令(dmon表示以实时监控的形式查看):
nvidia-smi dmon
各列含义:
| 列名 | 全称 / 解释 | 单位/说明 |
|---|---|---|
| gpu | GPU 索引 (Idx) | 系统中的 GPU 编号(从 0 开始),多 GPU 时用于区分不同显卡。 |
| pwr | Power Draw | 当前 GPU 功耗(瓦特,W)。 |
| gtemp | GPU Temperature | GPU 核心温度(摄氏度,℃)。 |
| mtemp | Memory Temperature | 显存温度(℃),- 表示无传感器或未支持。 |
| sm | Streaming Multiprocessor | 流处理器利用率(百分比,%),反映 CUDA 核心的计算负载。 |
| mem | Memory Utilization | 显存带宽利用率(%),非显存容量占用,表示显存控制器的繁忙程度。 |
| enc | Encoder Utilization | 视频编码器(如 NVENC)利用率(%)。 |
| dec | Decoder Utilization | 视频解码器(如 NVDEC)利用率(%)。 |
| mclk | Memory Clock | 显存时钟频率(MHz),越高表示显存速度越快。 |
| pclk | Processor Clock | GPU 核心时钟频率(MHz),反映 GPU 核心的当前运行速度。 |
sm 和 mem 高百分比表明 GPU 计算或显存带宽成为瓶颈。在深度训练时,需要关注 sm 和 mem 是否接近 100%,确保 GPU 满载。
GPU占用率确实低的解决方案
可以在PyTorch DataLoader里设置num_workers和pin_memory参数解决。注意:在windows上设置num_workers后,训练函数必须放到if __name__ == "__main__"里面,否则会报错。
注意:不要把num_workers设置的太大,创建worker也需要很多时间。可以从2开始加,只要保证使用nvidia-smi查看的GPU利用率在90%以上即可。然后调整batch_size,让显存占用率也在90%左右即可。
示例代码:
importtorchimporttorch.nnasnnimporttorch.optimasoptimimporttorch.utils.dataasdatafromtorchvisionimportdatasets,transforms num_epochs=20batch_size=100learning_rate=0.001transform=transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.5,),(0.5,))])train_dataset=datasets.MNIST(root="./data",train=True,transform=transform,download=True)test_dataset=datasets.MNIST(root="./data",train=False,transform=transform,download=True)train_loader=data.DataLoader(train_dataset,batch_size=batch_size,shuffle=True,num_workers=2,pin_memory=True)test_loader=data.DataLoader(test_dataset,batch_size=batch_size,shuffle=False)device=torch.device("cuda"iftorch.cuda.is_available()else"cpu")classCNNModel(nn.Module):def__init__(self):super().__init__()self.layer1=nn.Sequential(nn.Conv2d(1,32,kernel_size=5,stride=1,padding=2),nn.ReLU(),nn.MaxPool2d(kernel_size=2,stride=2),)self.layer2=nn.Sequential(nn.Conv2d(32,64,kernel_size=5,stride=1,padding=2),nn.ReLU(),nn.MaxPool2d(kernel_size=2,stride=2),)self.dropout=nn.Dropout()self.fc1=nn.Linear(7*7*64,1000)self.fc2=nn.Linear(1000,10)defforward(self,x):out=self.layer1(x)out=self.layer2(out)out=out.reshape(out.size(0),-1)out=self.dropout(out)out=self.fc1(out)out=self.fc2(out)returnout model=CNNModel().to(device)criterion=nn.CrossEntropyLoss()optimizer=optim.Adam(model.parameters(),lr=learning_rate)deftrain():model.train()forepochinrange(num_epochs):fori,(images,labels)inenumerate(train_loader):images=images.to(device)labels=labels.to(device)output=model(images)loss=criterion(output,labels)optimizer.zero_grad()loss.backward()optimizer.step()if(i+1)%100==0:print("Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}".format(epoch+1,num_epochs,i+1,len(train_loader),loss.item()))deftest():model.eval()withtorch.no_grad():total=0correct=0forimages,labelsintest_loader:images=images.to(device)labels=labels.to(device)output=model(images)_,predict=torch.max(output,1)total+=labels.size(0)correct+=(predict==labels).sum().item()print("Accuracy of 10000 test images: {} %".format(correct/total*100))if__name__=="__main__":train()test()原文:PyTorch训练GPU占用率低?别被任务管理器骗了,用这招看真实利用率 - 超腾开源