You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
注册

小参数网络中PyTorch训练速度慢于TensorFlow,求优化方法

PyTorch训练速度慢于TensorFlow的问题排查与优化

问题描述

我目前在使用一个小型结构化网络,虽然PyTorch因灵活性高是我的首选,但它的训练速度比TensorFlow慢很多——经过10次训练后,PyTorch的耗时几乎翻倍。是不是我的操作有问题?有没有办法提升PyTorch的计算效率?我复现了PyTorch的同款对比网络,代码如下:

PyTorch模型定义代码

import torch.nn as nn
import torch
import time
from torch.utils.data import DataLoader,TensorDataset
import numpy as np

## Parameters
learning_rate = 0.0005
num_of_epochs = 300
batch_size = 128

## Create Data
xx=torch.arange(40*640*60, dtype=torch.float32).view(640*60, 40)
ff=torch.arange(1*640*60, dtype=torch.float32).view(640*60, 1)
out=torch.arange(1*640*60, dtype=torch.float32).view(640*60, 1)

## Define the model
class Model(nn.Module):
    def __init__(self):
        super().__init__()
        self.lin = nn.Linear(40, 1, False)
        self.par = nn.Parameter(torch.Tensor(1))

    def forward(self, x, f):
        return torch.add(self.lin(x),self.par*f)

model = Model()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
loss_fun = torch.nn.MSELoss()

dataset = TensorDataset(xx,ff,out)
train_dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False)

PyTorch训练代码

%%time
## Training
model.train(True)
for i in range(n_train):
    start = time.time()
    for iter in range(num_of_epochs):
        train_loss = []
        for x, f, y in train_dataloader:
            # Zero your gradients for every batch!
            optimizer.zero_grad()

            # Make predictions for this batch
            out = model(x, f)

            # Compute the loss and its gradients
            loss = loss_fun(out, y)
            loss.backward()

            # Adjust learning weights
            optimizer.step()
            train_loss.append(loss.item())
        train_loss = np.mean(train_loss)
    end = time.time()
    exe_time['pytorch'].append(end-start)

问题排查与优化方案

1. 未启用CUDA加速(核心原因

你的代码全程使用CPU训练,而TensorFlow在Colab环境会自动启用GPU,这是速度差距的主要来源。解决方法:

  • 初始化模型时移到GPU:model = Model().to('cuda')
  • 训练循环中把批次数据移到GPU:
    for x, f, y in train_dataloader:
        x, f, y = x.to('cuda'), f.to('cuda'), y.to('cuda')
        # 后续训练步骤...
    
  • 可选:DataLoader设置pin_memory=True,加速CPU到GPU的数据传输。

2. 训练循环的状态重置问题

外层n_train循环中,你没有重新初始化模型和优化器,导致后续训练时模型已收敛,梯度更新效率降低,甚至可能因参数饱和增加计算开销。如果是重复测试耗时,每次循环都要重置:

for i in range(n_train):
    # 每次训练都重新初始化模型和优化器
    model = Model().to('cuda')
    optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
    start = time.time()
    # 后续epoch训练代码...

3. DataLoader效率优化

  • 开启多进程数据加载:设置num_workers=2(Colab环境建议2-4),减少数据加载等待时间:
    train_dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=False, num_workers=2, pin_memory=True)
    

4. 其他小优化

  • 清理显存:每次训练循环结束后执行torch.cuda.empty_cache(),避免显存泄漏导致的速度下降。
  • 优化器选择:如果任务允许,可尝试用SGD替代Adam,减少计算开销(但需调整学习率)。
  • 避免冗余计算:训练循环中train_loss用列表存储后转numpy均值,可改为用torch.mean直接计算,减少CPU-GPU数据交互。

内容的提问来源于stack exchange,提问作者MrMandarino

火山引擎 最新活动