Looking for help on why GPU is not used when I train a Pytorch model

Viewed 31

The machine I am using for training has 4 GPUs. I am "moving" classifier, loss function and tensors to GPU. But when I run nvidia-smi on the machine while training is ongoing, I see GPU utilization is very low (3%) on one core and 0 on other cores.

Questions I have are

  1. Is there an easier approach to ask Pytorch to use GPU and as many cores as available without me having to do so many .to(device) all over the place
  2. Is there something other than .to(device) that is needed to use GPU?
  3. Is there a way to see if training is happening on CPU vs GPU or is running nvidia-smi on the machine and looking at GPU utilization the only way?
  4. How do I interpret GPU utilization of 3% in nvidia-smi. Does it mean CPU is being used in many places? If yes, is there a way to debug what is making the training use CPU?
  5. Will setting num_workers to number of available cores in DataLoader class be enough to use multiple GPU cores? Is there any generic way to automatically learn number of GPU cores available?

Code used to train

random.seed(1234)
np.random.seed(1234)
torch.manual_seed(1234)
torch.cuda.manual_seed(1234)
torch.backends.cudnn.deterministic = True

start_time = time.time()
clf = MLP(len(X_training[0]), hidden_size=[100, 100, 100, 100, 100])
#Move to GPU if available
use_gpu = torch.cuda.is_available()
device = torch.device('cuda' if use_gpu else 'cpu')

# Define the loss function and optimizer
optimizer = torch.optim.Adam(clf.parameters(), lr=8e-4)
clf = clf.to(device)
loss_function = nn.BCELoss()
loss_function = loss_function.to(device)

# Run the training loop
# per_epoch_precision = []
# per_epoch_recall = []
for epoch in range(0, 150):
    # Set current loss value
    current_loss = 0.0
    dataset = MyDataset(X_training, y_training, use_gpu)
    kwargs = {'num_workers': 1, 'pin_memory': True} if use_gpu else {}
    trainloader = torch.utils.data.DataLoader(dataset, batch_size=10000, shuffle=True, **kwargs)

    # Iterate over the DataLoader for training data
    clf.train()  # set to train mode
    for i, data in enumerate(trainloader):
        # Get inputs
        inputs, targets = data
        inputs = inputs.to(device)
        targets = targets.to(device)

        # Zero the gradients
        optimizer.zero_grad()

        # Perform forward pass
        outputs = clf(inputs)

        # Compute loss
        targets = targets.float().unsqueeze(1)
        loss = loss_function(outputs, targets)

        # Perform backward pass
        loss.backward()

        # Perform optimization
        optimizer.step()

        # Print statistics
        current_loss += loss.item()
        if i % 20000 == 19999:
            print("Loss after mini-batch %5d: %.3f" % (i + 1, current_loss / 500))
            current_loss = 0.0

# Process is complete.
print("Training process has finished.")
print(f"Train time is {time.time() - start_time}")
class MyDataset(Dataset):

  def __init__(self, x, y, use_gpu=False):
    x = x.astype(np.float32)
    self.x_train = torch.from_numpy(x)
    self.y_train = torch.from_numpy(y.values)
    if use_gpu:
        device = torch.device("cuda")
        self.x_train.to(device)
        self.y_train.to(device)
    # self.y_train = torch.LongTensor(y.values, dtype=torch.int)


  def __len__(self):
    return len(self.y_train)
  
  def __getitem__(self,idx):
    return self.x_train[idx],self.y_train[idx]
class MLP(nn.Module):
    def __init__(self, input_size, hidden_size, act_fn=nn.ReLU(), use_dropout=False, drop_rate=0.25):
        super(MLP, self).__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.layers = nn.Sequential()
        if use_dropout:
            self.layers.append(nn.Dropout(p=drop_rate))
        self.layers.append(nn.Linear(self.input_size, self.hidden_size[0]))
        self.layers.append(act_fn)                
        for i in range(1, len(hidden_size)):
            if use_dropout:
                self.layers.append(nn.Dropout(p=drop_rate))
            self.layers.append(nn.Linear(self.hidden_size[i - 1], self.hidden_size[i]))
            self.layers.append(act_fn)
        
        if use_dropout:
            self.layers.append(nn.Dropout(p=drop_rate))
        self.layers.append(nn.Linear(self.hidden_size[-1], 1))
        self.layers.append(nn.Sigmoid())      

    def forward(self, x):
        return self.layers(x)
0 Answers
Related