Getting Started with Training on Intel Gaudi
On this Page
Getting Started with Training on Intel Gaudi¶
This guide provides simple steps for preparing a PyTorch model to run training on Intel® Gaudi® AI accelerator.
Make sure to install the PyTorch packages provided by Intel Gaudi. To set up the PyTorch environment, refer to the Installation Guide.The supported PyTorch versions are listed in the Support Matrix.
Once you are ready to migrate PyTorch models that run on GPU-based architecture to run on Gaudi, you can use the GPU Migration Toolkit. The GPU Migration toolkit automates the process of migration by replacing all Python API calls that have dependencies on GPU libraries with Gaudi-specific API calls, so you can run your model with fewer modifications.
Note
Installing public PyTorch packages is supported only when using public PyTorch with Eager mode and
torch.compile. For more details, see Public PyTorch Support.Refer to the PyTorch Known Issues and Limitations section for a list of current limitations.
Creating a Simple Training Example¶
The following sections provide two training examples using Eager mode with torch.compile and Lazy mode. For more details, refer to PyTorch Gaudi Theory of Operations.
Note
For more detailed training examples, refer to the MNIST model or to the PyTorch Torchvision.
Example with Eager Mode and torch.compile¶
Create a file named torch_compile.py with the code below:
1import torch
2import torch.nn as nn
3import torch.nn.functional as F
4import torch.optim as optim
5from torchvision import datasets, transforms
6from torch.optim.lr_scheduler import StepLR
7import os
8import sys
9import habana_frameworks.torch.core as htcore
10
11class Net(nn.Module):
12 def __init__(self):
13 super(Net, self).__init__()
14 self.conv1 = nn.Conv2d(1, 32, 3, 1)
15 self.conv2 = nn.Conv2d(32, 64, 3, 1)
16 self.dropout1 = nn.Dropout(0.25)
17 self.dropout2 = nn.Dropout(0.5)
18 self.fc1 = nn.Linear(7744, 128)
19 self.fc2 = nn.Linear(128, 10)
20
21 def forward(self, x):
22 x = self.conv1(x)
23 x = F.relu(x)
24 x = self.conv2(x)
25 x = F.relu(x)
26 x = F.max_pool2d(x, 3, 2)
27 x = self.dropout1(x)
28 x = torch.flatten(x, 1)
29 x = self.fc1(x)
30 x = F.relu(x)
31 x = self.dropout2(x)
32 x = self.fc2(x)
33 output = F.log_softmax(x, dim=1)
34 return output
35
36def train(model, device, train_loader, optimizer, epoch):
37 model.train()
38 model = torch.compile(model,backend="hpu_backend")
39
40 def train_function(data, target):
41 optimizer.zero_grad()
42 output = model(data)
43 loss = F.nll_loss(output, target)
44 loss.backward()
45 optimizer.step()
46 return loss
47
48 training_step = 0
49 for batch_idx, (data, target) in enumerate(train_loader):
50 data, target = data.to(device), target.to(device)
51 loss = train_function(data, target)
52 if batch_idx % 10 == 0:
53 print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}'.format(
54 epoch, batch_idx *
55 len(data), len(train_loader.dataset),
56 100. * batch_idx / len(train_loader), loss.item()))
57
58def main():
59 device = torch.device("hpu")
60
61 model = Net().to(device)
62
63 optimizer = optim.Adadelta(model.parameters(), lr=1.0)
64
65 transform = transforms.Compose([
66 transforms.ToTensor(),
67 transforms.Normalize((0.1307,), (0.3081,))
68 ])
69
70 dataset = datasets.MNIST('./data', train=True, download=True, transform=transform)
71 train_loader = torch.utils.data.DataLoader(dataset, batch_size=500)
72
73 scheduler = StepLR(optimizer, step_size=1, gamma=0.7)
74 for epoch in range(0,1):
75 train(model, device, train_loader, optimizer, epoch)
76 scheduler.step()
77
78 print("torch.compile training completed.")
79
80if __name__ == '__main__':
81 main()
This is a simple PyTorch CNN model with torch.compile enabled. The Gaudi-specific lines are explained below.
Line 9 - Import the Intel Gaudi PyTorch framework:
import habana_frameworks.torch.core as htcore
Line 38 - Wrap the model in
torch.compilefunction and set the backend tohpu_backend:model = torch.compile(model,backend="hpu_backend")
If you want to run the model in Eager mode without
torch.compile, comment out this line.Line 59 - Target the Gaudi device:
device = torch.device("hpu")
Executing the Example¶
After creating the torch_compile.py, perform the following:
Set PYTHON to Python executable:
export PYTHON=/usr/bin/python3.10
Note
The Python version depends on the operating system. Refer to the Support Matrix for a full list of supported operating systems and Python versions.
Execute the
torch_compile.py:$PYTHON torch_compile.py
Example with Lazy Mode¶
Create a file named example.py with the code below:
1import torch
2import torch.nn as nn
3import torch.optim as optim
4import torch.nn.functional as F
5import torchvision
6import torchvision.transforms as transforms
7import os
8
9# Import Habana Torch Library
10import habana_frameworks.torch.core as htcore
11
12class SimpleModel(nn.Module):
13 def __init__(self):
14 super(SimpleModel, self).__init__()
15
16 self.fc1 = nn.Linear(784, 256)
17 self.fc2 = nn.Linear(256, 64)
18 self.fc3 = nn.Linear(64, 10)
19
20 def forward(self, x):
21
22 out = x.view(-1,28*28)
23 out = F.relu(self.fc1(out))
24 out = F.relu(self.fc2(out))
25 out = self.fc3(out)
26
27 return out
28
29def train(net,criterion,optimizer,trainloader,device):
30
31 net.train()
32 train_loss = 0.0
33 correct = 0
34 total = 0
35
36 for batch_idx, (data, targets) in enumerate(trainloader):
37
38 data, targets = data.to(device), targets.to(device)
39
40 optimizer.zero_grad()
41 outputs = net(data)
42 loss = criterion(outputs, targets)
43
44 loss.backward()
45
46 # API call to trigger execution
47 htcore.mark_step()
48
49 optimizer.step()
50
51 # API call to trigger execution
52 htcore.mark_step()
53
54 train_loss += loss.item()
55 _, predicted = outputs.max(1)
56 total += targets.size(0)
57 correct += predicted.eq(targets).sum().item()
58
59 train_loss = train_loss/(batch_idx+1)
60 train_acc = 100.0*(correct/total)
61 print("Training loss is {} and training accuracy is {}".format(train_loss,train_acc))
62
63def test(net,criterion,testloader,device):
64
65 net.eval()
66 test_loss = 0
67 correct = 0
68 total = 0
69
70 with torch.no_grad():
71
72 for batch_idx, (data, targets) in enumerate(testloader):
73
74 data, targets = data.to(device), targets.to(device)
75
76 outputs = net(data)
77 loss = criterion(outputs, targets)
78
79 # API call to trigger execution
80 htcore.mark_step()
81
82 test_loss += loss.item()
83 _, predicted = outputs.max(1)
84 total += targets.size(0)
85 correct += predicted.eq(targets).sum().item()
86
87 test_loss = test_loss/(batch_idx+1)
88 test_acc = 100.0*(correct/total)
89 print("Testing loss is {} and testing accuracy is {}".format(test_loss,test_acc))
90
91def main():
92
93 epochs = 20
94 batch_size = 128
95 lr = 0.01
96 milestones = [10,15]
97 load_path = './data'
98 save_path = './checkpoints'
99
100 if(not os.path.exists(save_path)):
101 os.makedirs(save_path)
102
103 # Target the Gaudi HPU device
104 device = torch.device("hpu")
105
106 # Data
107 transform = transforms.Compose([
108 transforms.ToTensor(),
109 ])
110
111 trainset = torchvision.datasets.MNIST(root=load_path, train=True,
112 download=True, transform=transform)
113 trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,
114 shuffle=True, num_workers=2)
115 testset = torchvision.datasets.MNIST(root=load_path, train=False,
116 download=True, transform=transform)
117 testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,
118 shuffle=False, num_workers=2)
119
120 net = SimpleModel()
121 net.to(device)
122
123 criterion = nn.CrossEntropyLoss()
124 optimizer = optim.SGD(net.parameters(), lr=lr,
125 momentum=0.9, weight_decay=5e-4)
126 scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=milestones, gamma=0.1)
127
128 for epoch in range(1, epochs+1):
129 print("=====================================================================")
130 print("Epoch : {}".format(epoch))
131 train(net,criterion,optimizer,trainloader,device)
132 test(net,criterion,testloader,device)
133
134 torch.save(net.state_dict(), os.path.join(save_path,'epoch_{}.pth'.format(epoch)))
135
136 scheduler.step()
137
138if __name__ == '__main__':
139 main()
The example.py presents a basic PyTorch code example. The Gaudi-specific lines are explained below.
Line 10 - Import
habana_frameworks.torch.core:import habana_frameworks.torch.core as htcore
Line 104 - Target the Gaudi device:
device = torch.device("hpu")
Lines 47, 52, 80 - In Lazy mode,
mark_step()must be added in all training scripts right afterloss.backward()andoptimizer.step(). For further details onmark_step, refer to mark_step section.htcore.mark_step()
Executing the Example¶
After creating the example.py, perform the following:
Set PYTHON to Python executable:
export PYTHON=/usr/bin/python3.10
Note
The Python version depends on the operating system. Refer to the Support Matrix for a full list of supported operating systems and Python versions.
Execute the
example.py:PT_HPU_LAZY_MODE=1 $PYTHON example.py
To use Lazy mode, the
PT_HPU_LAZY_MODE=1environment variable must be set since Eager mode withtorch.compileis the default mode. Refer to Runtime Environment Variables for more information.
The following should appear as part of the output:
Epoch 1/5
469/469 [==============================] - 1s 3ms/step - loss: 1.2647 - accuracy: 0.7208
Epoch 2/5
469/469 [==============================] - 1s 2ms/step - loss: 0.7113 - accuracy: 0.8433
Epoch 3/5
469/469 [==============================] - 1s 2ms/step - loss: 0.5845 - accuracy: 0.8606
Epoch 4/5
469/469 [==============================] - 1s 2ms/step - loss: 0.5237 - accuracy: 0.8688
Epoch 5/5
469/469 [==============================] - 1s 2ms/step - loss: 0.4865 - accuracy: 0.8749
313/313 [==============================] - 1s 2ms/step - loss: 0.4482 - accuracy: 0.8869
Since the first iteration includes graph compilation time, you can see the first iteration takes longer to run than later iterations. The software stack compiles the graph and saves the recipe to cache. Unless the graph changes or a new graph comes in, no recompilation is needed during the training. Typically, the graph compilation happens at the beginning of the training and at the beginning of the evaluation.
Saving Model Checkpoints with torch.save¶
When working with convolutional neural networks, using torch.save to save an HPU model’s state_dict or tensors may result in errors.
This issue can occur for tensors with NCHW layout which are internally permuted on the device.
As a workaround, move the model or output tensors to CPU before calling torch.save:
# Move model to CPU before saving
torch.save(model.cpu().state_dict(), 'model_checkpoint.pth')
# Move tensor to CPU before saving
torch.save(output_tensor.cpu(), 'output_tensor.pth')
Torch Multiprocessing for DataLoaders¶
If training scripts use multiprocessing with multiple workers for PyTorch dataloader, change the start method to spawn or forkserver using the
PyTorch API multiprocessing.set_start_method(...). For example:
torch.multiprocessing.set_start_method('spawn')
Default start method is fork which may result in undefined behavior.