Некоторые варианты, которые я пробовал:
< ol>
[*]Я перешел от меньшего размера партии (16) к большему (256).
[*]Я экспериментировал с добавлением до 8 дополнительных скрытых слоев.
[*]Я экспериментировал с аккумулировать_град_батчи в параметрах трейнера.
К сожалению, ни одна из этих настроек не привела к каким-либо улучшениям. Возможно, моя модель слишком проста для того, чтобы процесс с несколькими графическими процессорами был лучше, но я слишком новичок в обучении с несколькими графическими процессорами, чтобы заявить об этой проблеме, и мои эксперименты не привели к каким-либо улучшениям. Я видел варианты этого вопроса о переполнении стека, но они обычно направлены на устранение ошибок. В моем случае мне интересно, почему производительность так снижается, особенно при использовании кода молнии pytorch.
Мой вопрос: Есть ли какие-либо ключевые проблемы с этим фиктивным примером, который приведет к тому, что процесс с одним графическим процессором превзойдет процесс с несколькими графическими процессорами?
Код: Выделить всё
import pytorch_lightning as pl
from pytorch_lightning import LightningModule, LightningDataModule
from torch import nn
from torch.utils.data import Dataset, DataLoader
import torch
import time
import wandb
from pytorch_lightning.loggers import WandbLogger
import pynvml
class SimpleDataset(Dataset):
def __init__(self, size):
self.size = size
def __len__(self):
return self.size
def __getitem__(self, idx):
# Generate some random data
x = torch.randn(1, 10)
y = torch.randn(1)
return x, y
class SimpleDataModule(LightningDataModule):
def __init__(self, batch_size, size):
super().__init__()
self.batch_size = batch_size
self.size = size
def setup(self, stage=None):
self.dataset = SimpleDataset(self.size)
def train_dataloader(self):
return DataLoader(self.dataset, batch_size=self.batch_size, shuffle=True)
def val_dataloader(self):
return DataLoader(self.dataset, batch_size=self.batch_size)
class SimpleModel(LightningModule):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10, 256)
self.fc2 = nn.Linear(256, 256)
self.fc3 = nn.Linear(256, 256)
self.fc4 = nn.Linear(256, 1)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
x = torch.relu(self.fc3(x))
x = self.fc4(x)
return x
def training_step(self, batch, batch_idx):
x, y = batch
y_pred = self(x)
loss = nn.MSELoss()(y_pred, y)
self.log('train_loss', loss)
# Get individual GPU utilization
pynvml.nvmlInit()
utilization = []
for i in range(pynvml.nvmlDeviceGetCount()):
handle = pynvml.nvmlDeviceGetHandleByIndex(i)
utilization.append(pynvml.nvmlDeviceGetUtilizationRates(handle).gpu)
pynvml.nvmlShutdown()
# Log individual GPU utilization
for i, util in enumerate(utilization):
self.log(f'gpu_{i}_utilization', util)
return loss
def validation_step(self, batch, batch_idx):
x, y = batch
y_pred = self(x)
loss = nn.MSELoss()(y_pred, y)
self.log('val_loss', loss)
return loss
def configure_optimizers(self):
return torch.optim.Adam(self.parameters(), lr=0.01)
data_module = SimpleDataModule(batch_size=256, size=5000)
model = SimpleModel()
start_time = time.time()
wandb_logger = WandbLogger(project='simple_model')
trainer = pl.Trainer(strategy='ddp', devices=3, max_epochs=200, accumulate_grad_batches=3, logger=wandb_logger)
trainer.fit(model, data_module)
if trainer.is_global_zero:
end_time = time.time()
elapsed_time = end_time - start_time
print(f"Training completed in {elapsed_time:.2f} seconds")
Есть ли в коде какой-либо явный недостаток, исправление которого позволило бы процессу обучения 3G превзойти процесс обучения 1G?
Подробнее здесь: https://stackoverflow.com/questions/792 ... ning-dummy