为何PyTorch 2.0比TensorFlow 2.0在CUDA环境下运行慢3倍?
PyTorch 2.0 vs TensorFlow 2.0 训练性能差异问题
我正在测试TensorFlow 2.0与PyTorch 2.0的运行速度(刚接触PyTorch),在相同模型架构、批次大小、优化器且均启用CUDA的前提下,发现PyTorch的训练耗时约为TensorFlow的3倍(TF耗时1分钟,PT耗时3分钟),且验证集精度更低(TF为83%,PT为78%)。
同时观察到:TensorFlow占用约60%的CUDA使用率及全部专用GPU显存,而PyTorch的CUDA利用率在0%-30%间波动,显存占用极低。已排除CUDA_LAUNCH_BLOCKING参数导致的问题(代码中未设置该参数)。
TensorFlow 代码
(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.fashion_mnist.load_data() model = tf.keras.Sequential([ tf.keras.layers.Flatten(input_shape=(28,28)), tf.keras.layers.Dense(512, activation="relu"), tf.keras.layers.Dense(512, activation="relu"), tf.keras.layers.Dense(10, activation="softmax") ]) model.compile(optimizer=tf.keras.optimizers.SGD(1e-3), loss="sparse_categorical_crossentropy", metrics=["accuracy"]) model.fit(train_images, train_labels, epochs=20, batch_size=64, validation_data=(test_images, test_labels))
PyTorch 代码
import torch from torch import nn from torch.utils.data import DataLoader from torchvision import datasets from torchvision.transforms import ToTensor device = torch.device("cuda") training_data = datasets.FashionMNIST( root="data", train=True, download=True, transform=ToTensor() ) test_data = datasets.FashionMNIST( root="data", train=False, download=True, transform=ToTensor() ) train_dataloader = DataLoader(training_data, batch_size=64) test_dataloader = DataLoader(test_data, batch_size=64) class NeuralNetwork(nn.Module): def __init__(self): super().__init__() self.flatten = nn.Flatten() self.linear_relu_stack = nn.Sequential( nn.Linear(28*28, 512), nn.ReLU(), nn.Linear(512, 512), nn.ReLU(), nn.Linear(512, 10), ) def forward(self, x): x = self.flatten(x) logits = self.linear_relu_stack(x) return logits model = NeuralNetwork() model.to(device) learning_rate = 1e-3 batch_size = 64 epochs = 5 loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) def train_loop(dataloader, model, loss_fn, optimizer): size = len(dataloader.dataset) model.train() for batch, (X, y) in enumerate(dataloader): X, y = X.to(device), y.to(device) pred = model(X) loss = loss_fn(pred, y) loss.backward() optimizer.step() optimizer.zero_grad() if batch % 100 == 0: loss, current = loss.item(), (batch + 1) * len(X) print(f"loss: {loss:>7f} [{current:>5d}/{size:>5d}]") def test_loop(dataloader, model, loss_fn): model.eval() size = len(dataloader.dataset) num_batches = len(dataloader) test_loss, correct = 0, 0 with torch.no_grad(): for X, y in dataloader: X, y = X.to(device), y.to(device) pred = model(X) test_loss += loss_fn(pred, y).item() correct += (pred.argmax(1) == y).type(torch.float).sum().item() test_loss /= num_batches correct /= size print(f"Test Error: \n Accuracy: {(100*correct):>0.1f}%, Avg loss: {test_loss:>8f} \n") loss_fn = nn.CrossEntropyLoss() optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate) epochs = 20 for t in range(epochs): print(f"Epoch {t+1}\n-------------------------------") train_loop(train_dataloader, model, loss_fn, optimizer) test_loop(test_dataloader, model, loss_fn) print("Done!")
硬件配置
- RTX 3060
- Intel i7-10700(超频至~4.2GHz)
- 64GB内存
已尝试的优化措施
- 增加DataLoader的workers数、固定内存,仅为20轮训练节省约15秒
- 设置
torch.backends.cudnn.benchmark = True,无任何效果
现寻求该现象的原因及优化方案。
内容的提问来源于stack exchange,提问作者Addicted2Cookies
相关产品推荐
相关产品推荐

