[tune/sgd] Document func_trainable and add checkpoint context (#9739)

Co-authored-by: krfricke <krfricke@users.noreply.github.com>
Co-authored-by: Amog Kamsetty <amogkam@users.noreply.github.com>
This commit is contained in:
Richard Liaw
2020-07-30 09:46:37 -07:00
committed by GitHub
co-authored by krfricke Amog Kamsetty
parent e540e425e4
commit 0c3b9ebeef
23 changed files with 619 additions and 452 deletions
@@ -213,16 +213,7 @@ In GCP, you can use the following configuration modification:
scheduling:
- preemptible: true
Spot instances may be removed suddenly while trials are still running. Often times this may be difficult to deal with when using other distributed hyperparameter optimization frameworks. Tune allows users to mitigate the effects of this by preserving the progress of your model training through checkpointing.
The easiest way to do this is to subclass the pre-defined ``Trainable`` class and implement ``save_checkpoint``, and ``load_checkpoint`` abstract methods, as seen in the example below:
.. literalinclude:: /../../python/ray/tune/examples/mnist_pytorch_trainable.py
:language: python
:start-after: __trainable_example_begin__
:end-before: __trainable_example_end__
This can then be used similarly to the Function API as before:
Spot instances may be removed suddenly while trials are still running. Often times this may be difficult to deal with when using other distributed hyperparameter optimization frameworks. Tune allows users to mitigate the effects of this by preserving the progress of your model training through :ref:`checkpointing <tune-function-checkpointing>`.
.. literalinclude:: /../../python/ray/tune/tests/tutorial.py
:language: python
@@ -25,6 +25,8 @@ need to
3. add checkpointing (optional),
4. and define the search space for the model tuning
Optionally, you can seamlessly leverage :ref:`DistributedDataParallel training <tune-torch-ddp>` for each individual Pytorch model within Tune.
.. note::
To run this example, you will need to install the following:
@@ -74,15 +76,16 @@ The train function
Now it gets interesting, because we introduce some changes to the example `from the PyTorch
documentation <https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html>`_.
We wrap the training script in a function ``train_cifar(config, checkpoint=None)``. As you
We wrap the training script in a function ``train_cifar(config, checkpoint_dir=None)``. As you
can guess, the ``config`` parameter will receive the hyperparameters we would like to
train with. The ``checkpoint`` parameter is used to restore checkpoints.
train with. The ``checkpoint_dir`` parameter is used to restore checkpoints.
.. code-block:: python
net = Net(config["l1"], config["l2"])
if checkpoint:
if checkpoint_dir:
checkpoint = os.path.join(checkpoint_dir, "checkpoint")
net.load_state_dict(torch.load(checkpoint))
The learning rate of the optimizer is made configurable, too:
@@ -97,6 +100,7 @@ with which we iterate through the training and test sets are configurable as wel
Adding (multi) GPU support with DataParallel
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Image classification benefits largely from GPUs. Luckily, we can continue to use
PyTorch's abstractions in Ray Tune. Thus, we can wrap our model in ``nn.DataParallel``
to support data parallel training on multiple GPUs:
@@ -132,10 +136,9 @@ The most interesting part is the communication with Tune:
.. code-block:: python
checkpoint_dir = tune.make_checkpoint_dir(epoch)
path = os.path.join(checkpoint_dir, "checkpoint")
torch.save((net.state_dict(), optimizer.state_dict()), path)
tune.save_checkpoint(path)
with tune.checkpoint_dir(epoch) as checkpoint_dir:
path = os.path.join(checkpoint_dir, "checkpoint")
torch.save((net.state_dict(), optimizer.state_dict()), path)
tune.report(loss=(val_loss / val_steps), accuracy=correct / total)
@@ -273,6 +276,75 @@ be confirmed on the test set.
So that's it! You can now tune the parameters of your PyTorch models.
.. _tune-torch-ddp:
Advanced: Distributed training with DistributedDataParallel
-----------------------------------------------------------
Some models require multiple nodes to train in a short amount of time. Ray Tune allows you to easily do distributed data parallel training in addition to distributed hyperparameter tuning.
You can wrap your model in ``torch.nn.parallel.DistributedDataParallel`` to support distributed data parallel training:
.. code-block:: python
from ray.util.sgd.torch import is_distributed_trainable
from torch.nn.parallel import DistributedDataParallel
def train_cifar(config, checkpoint_dir=None, data_dir=None):
net = Net(config["l1"], config["l2"])
device = "cpu"
#### Using distributed data parallel training
if is_distributed_trainable():
net = DistributedDataParallel(net)
if torch.cuda.is_available():
device = "cuda"
net.to(device)
If using checkpointing, be sure to use a :ref:`special checkpoint context manager <tune-ddp-doc>`, ``distributed_checkpoint_dir`` that avoids redundant checkpointing across multiple processes:
.. code-block:: python
from ray.util.sgd.torch import distributed_checkpoint_dir
#### Using distributed data parallel training
# Inside `def train_cifar(...)`,
# replace tune.checkpoint_dir() with the following
# Avoids redundant checkpointing on different processes.
with distributed_checkpoint_dir(step=epoch) as checkpoint_dir:
path = os.path.join(checkpoint_dir, "checkpoint")
torch.save((net.state_dict(), optimizer.state_dict()), path)
Finally, we need to tell Ray Tune to start multiple distributed processes at once by using ``ray.tune.integration.torch.DistributedTrainableCreator`` (:ref:`docs <tune-ddp-doc>`). This is essentially equivalent to running ``torch.distributed.launch`` for each hyperparameter trial:
.. code-block:: python
# You'll probably want to be running on a distributed Ray cluster.
# ray.init(address="auto")
from ray.util.sgd.integration.torch import DistributedTrainableCreator
distributed_train_cifar = DistributedTrainableCreator(
partial(train_cifar, data_dir=data_dir),
use_gpu=True,
num_workers=2, # number of parallel workers to use
num_cpus_per_worker=8
)
tune.run(
distributed_train_cifar,
resources_per_trial=None,
config=config,
num_samples=num_samples,
...
)
See an :doc:`end-to-end example here </tune/examples/ddp_mnist_torch>`.
If you consider switching to PyTorch Lightning to get rid of some of your boilerplate
training code, please know that we also have a walkthrough on :doc:`how to use Tune with
PyTorch Lightning models <tune-pytorch-lightning>`.
PyTorch Lightning models <tune-pytorch-lightning>`.