This example demonstrates using a Nvidia GPU for training a model.
The nodes for this example need to run on a machine providing a Nvidia GPU with enough GPU memory (and from a not-too-old model, so that it is supported by PyTorch).
If GPU doesn't have enough memory you will get a out of memory error at run time.
You can check the Fed-BioMed GPU documentation for some background about using GPUs with Fed-BioMed.
Start the network¶
Before running this notebook, start the network with ./scripts/fedbiomed_run network
Set up the nodes up¶
We need at least 1 node, let's test using 3 nodes.
For each node, add the MNIST dataset :
./scripts/fedbiomed_run node config config1.ini add ./scripts/fedbiomed_run node config config2.ini add ./scripts/fedbiomed_run node config config3.ini add
- Select option 2 (default) to add MNIST to the node
- Confirm default tags by hitting "y" and ENTER
- Pick the folder where MNIST is already downloaded (or where to download MNIST)
Check that your data has been added by executing
./scripts/fedbiomed_run node config config1.ini list ./scripts/fedbiomed_run node config config2.ini list ./scripts/fedbiomed_run node config config3.ini list
Run the first node using
./scripts/fedbiomed_run node config config1.ini run --gpu
so that the node offers to use GPU for training, with the default GPU device.
Run the second node using
./scripts/fedbiomed_run node config config2.ini run --gpu-only --gpunum 1
so that the node enforces use of GPU for training even if the researcher doesn't request it, and requests using the 2nd GPU (device 1) but will fallback to default device if you don't have 2 GPUs on this machine.
Run the third node using
./scripts/fedbiomed_run node config config3.ini run
so that the node doesn't offer to use GPU for training (default behaviour).
Wait until you get
Starting task manager
for each node, it means you are online.
Define the experiment model¶
All this part is the same as when running a model using CPU : model in unchanged
Declare a torch.nn MyTrainingPlan class to send for training on the node
from fedbiomed.researcher.environ import environ
import tempfile
tmp_dir_model = tempfile.TemporaryDirectory(dir=environ['TMP_DIR']+'/')
model_file = tmp_dir_model.name + '/class_export_mnist.py'
%%writefile "$model_file"
import torch
import torch.nn as nn
from fedbiomed.common.torchnn import TorchTrainingPlan
from torch.utils.data import DataLoader
from torchvision import datasets, transforms
# Here we define the model to be used.
# You can use any class name (here 'Net')
class MyTrainingPlan(TorchTrainingPlan):
def __init__(self, model_args: dict = {}):
super(MyTrainingPlan, self).__init__(model_args)
self.conv1 = nn.Conv2d(1, 32, 3, 1)
self.conv2 = nn.Conv2d(32, 64, 3, 1)
self.dropout1 = nn.Dropout(0.25)
self.dropout2 = nn.Dropout(0.5)
self.fc1 = nn.Linear(9216, 128)
self.fc2 = nn.Linear(128, 10)
# Here we define the custom dependencies that will be needed by our custom Dataloader
# In this case, we need the torch DataLoader classes
# Since we will train on MNIST, we need datasets and transform from torchvision
deps = ["from torchvision import datasets, transforms",
"from torch.utils.data import DataLoader"]
self.add_dependency(deps)
def forward(self, x):
x = self.conv1(x)
x = F.relu(x)
x = self.conv2(x)
x = F.relu(x)
x = F.max_pool2d(x, 2)
x = self.dropout1(x)
x = torch.flatten(x, 1)
x = self.fc1(x)
x = F.relu(x)
x = self.dropout2(x)
x = self.fc2(x)
output = F.log_softmax(x, dim=1)
return output
def training_data(self, batch_size = 48):
# Custom torch Dataloader for MNIST data
transform = transforms.Compose([transforms.ToTensor(),
transforms.Normalize((0.1307,), (0.3081,))])
dataset1 = datasets.MNIST(self.dataset_path, train=True, download=False, transform=transform)
train_kwargs = {'batch_size': batch_size, 'shuffle': True}
data_loader = torch.utils.data.DataLoader(dataset1, **train_kwargs)
return data_loader
def training_step(self, data, target):
output = self.forward(data)
loss = torch.nn.functional.nll_loss(output, target)
return loss
Define the experiment parameters¶
model_args
are used by the researcher to request the nodes to use GPU for training, if the node has a GPU and offers to use it.
model_args = {
# Model wants to use GPU (or not) if available on node and proposed by node
'use_gpu': True
}
training_args = {
'batch_size': 48,
'lr': 1e-3,
'epochs': 1,
'dry_run': False,
'batch_maxnum': 100 # Fast pass for development : only use ( batch_maxnum * batch_size ) samples
}
Declare and run the experiment¶
All this part is the same as when running a model using CPU : experiment declaration and running is unchanged
from fedbiomed.researcher.experiment import Experiment
from fedbiomed.researcher.aggregators.fedavg import FedAverage
tags = ['#MNIST', '#dataset']
rounds = 2
exp = Experiment(tags=tags,
#nodes=None,
model_path=model_file,
model_args=model_args,
model_class='MyTrainingPlan',
training_args=training_args,
round_limit=rounds,
aggregator=FedAverage(),
node_selection_strategy=None)
Let's start the experiment.
By default, this function doesn't stop until all the round_limit
rounds are done for all the nodes
exp.run()
You have completed training a TorchTrainingPlan
using a GPU for acceleration.