View a markdown version of this page

テンソル並列処理を使用して SageMaker 分散モデル並列トレーニングジョブを実行する - Amazon SageMaker AI

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

テンソル並列処理を使用して SageMaker 分散モデル並列トレーニングジョブを実行する

このセクションでは、以下を行います。

  • テンソル並列処理を使用するように SageMaker PyTorch ModelTrainer と SageMaker モデル並列処理オプションを設定する方法。

  • 拡張 smdistributed.modelparallel モジュールを使用してトレーニングスクリプトをテンソル並列処理に適合させる方法。

smdistributed.modelparallel モジュールに関する詳細ついては、SageMaker Python SDK ドキュメントの「SageMaker 分散モデル並列 API」を参照してください。

テンソル並列処理のみ

以下は、パイプライン並列処理を使用せずに、テンソル並列処理を単独でアクティブにする分散トレーニングオプションの例です。mpi_options および smp_options ディクショナリを設定して、分散トレーニングオプションを SageMaker PyTorch ModelTrainer に指定します。

注記

拡張メモリ保存機能は、SageMaker モデル並列処理ライブラリ v1.6.0 以降を実装する PyTorch 用の Deep Learning Containers を通じて利用できます。

SageMaker PyTorch ModelTrainer を設定する

from sagemaker.train.configs import SourceCode, Compute, InputData from sagemaker.core import image_uris mpi_options = { "enabled" : True, "processes_per_host" : 8,               # 8 processes "custom_mpi_options" : "--mca btl_vader_single_copy_mechanism none " }                 smp_options = { "enabled":True, "parameters": { "pipeline_parallel_degree": 1,    # alias for "partitions" "placement_strategy": "cluster", "tensor_parallel_degree": 4,      # tp over 4 devices "ddp": True } }                # Retrieve the training image for the desired PyTorch version training_image = image_uris.retrieve( framework="pytorch", region="us-west-2", version='1.13.1', py_version='py36', instance_type='ml.p3.16xlarge', image_scope="training" ) smp_model_trainer = ModelTrainer( training_image=training_image, source_code=SourceCode(entry_script='your_training_script.py'), role=role, compute=Compute( instance_type='ml.p3.16xlarge', instance_count=1 ), sagemaker_session=sagemaker_session, distribution={ "smdistributed": {"modelparallel": smp_options}, "mpi": mpi_options }, base_job_name="SMD-MP-demo", ) smp_model_trainer.train(input_data_config=[ InputData(channel_name="training", data_source='s3://my_bucket/my_training_data/') ])
ヒント

distribution のパラメータの完全なリストを検索するには、SageMaker Python SDK のドキュメントの「モデル並列処理の設定パラメーター」を参照してください。

PyTorch トレーニングスクリプトを適合させる

次のトレーニングスクリプト例は、SageMaker モデル並列処理ライブラリをトレーニングスクリプトに適応させる方法を示しています。この例では、スクリプトの名前を your_training_script.py としています。

import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchnet.dataset import SplitDataset from torchvision import datasets import smdistributed.modelparallel.torch as smp class Net(nn.Module):     def __init__(self):         super(Net, self).__init__()         self.conv1 = nn.Conv2d(1, 32, 3, 1)         self.conv2 = nn.Conv2d(32, 64, 3, 1)         self.fc1 = nn.Linear(9216, 128)         self.fc2 = nn.Linear(128, 10)     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 = torch.flatten(x, 1)         x = self.fc1(x)         x = F.relu(x)         x = self.fc2(x)         return F.log_softmax(x, 1) def train(model, device, train_loader, optimizer):     model.train()     for batch_idx, (data, target) in enumerate(train_loader):         # smdistributed: Move input tensors to the GPU ID used by         # the current process, based on the set_device call.         data, target = data.to(device), target.to(device)         optimizer.zero_grad()         output = model(data)         loss = F.nll_loss(output, target, reduction="mean")         loss.backward()         optimizer.step() # smdistributed: Initialize the backend smp.init() # smdistributed: Set the device to the GPU ID used by the current process. # Input tensors should be transferred to this device. torch.cuda.set_device(smp.local_rank()) device = torch.device("cuda") # smdistributed: Download only on a single process per instance. # When this is not present, the file is corrupted by multiple processes trying # to download and extract at the same time if smp.local_rank() == 0:     dataset = datasets.MNIST("../data", train=True, download=False) smp.barrier() # smdistributed: Shard the dataset based on data parallel ranks if smp.dp_size() > 1:     partitions_dict = {f"{i}": 1 / smp.dp_size() for i in range(smp.dp_size())}     dataset = SplitDataset(dataset, partitions=partitions_dict)     dataset.select(f"{smp.dp_rank()}") train_loader = torch.utils.data.DataLoader(dataset, batch_size=64) # smdistributed: Enable tensor parallelism for all supported modules in the model # i.e., nn.Linear in this case. Alternatively, we can use # smp.set_tensor_parallelism(model.fc1, True) # to enable it only for model.fc1 with smp.tensor_parallelism():     model = Net() # smdistributed: Use the DistributedModel wrapper to distribute the # modules for which tensor parallelism is enabled model = smp.DistributedModel(model) optimizer = optim.AdaDelta(model.parameters(), lr=4.0) optimizer = smp.DistributedOptimizer(optimizer) train(model, device, train_loader, optimizer)

テンソル並列処理とパイプライン並列処理の組み合わせ

以下は、テンソル並列処理とパイプライン並列処理の組み合わせを有効にする分散トレーニングオプションの例です。SageMaker PyTorch ModelTrainer を設定するときに、 パラメータmpi_optionssmp_optionsパラメータを設定して、テンソル並列処理でモデル並列オプションを指定します。

注記

拡張メモリ保存機能は、SageMaker モデル並列処理ライブラリ v1.6.0 以降を実装する PyTorch 用の Deep Learning Containers を通じて利用できます。

SageMaker PyTorch ModelTrainer を設定する

mpi_options = { "enabled" : True, "processes_per_host" : 8,               # 8 processes "custom_mpi_options" : "--mca btl_vader_single_copy_mechanism none " }                 smp_options = { "enabled":True, "parameters": { "microbatches": 4, "pipeline_parallel_degree": 2,    # alias for "partitions" "placement_strategy": "cluster", "tensor_parallel_degree": 2,      # tp over 2 devices "ddp": True } }                # Retrieve the training image for the desired PyTorch version training_image = image_uris.retrieve( framework="pytorch", region="us-west-2", version='1.13.1', py_version='py36', instance_type='ml.p3.16xlarge', image_scope="training" ) smp_model_trainer = ModelTrainer( training_image=training_image, source_code=SourceCode(entry_script='your_training_script.py'), role=role, compute=Compute( instance_type='ml.p3.16xlarge', instance_count=1 ), sagemaker_session=sagemaker_session, distribution={ "smdistributed": {"modelparallel": smp_options}, "mpi": mpi_options }, base_job_name="SMD-MP-demo", ) smp_model_trainer.train(input_data_config=[ InputData(channel_name="training", data_source='s3://my_bucket/my_training_data/') ])

PyTorch トレーニングスクリプトを適合させる

次のトレーニングスクリプト例は、SageMaker モデル並列処理ライブラリをトレーニングスクリプトに適応させる方法を示しています。トレーニングスクリプトには、smp.step デコレーター:

import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim from torchnet.dataset import SplitDataset from torchvision import datasets import smdistributed.modelparallel.torch as smp class Net(nn.Module):     def __init__(self):         super(Net, self).__init__()         self.conv1 = nn.Conv2d(1, 32, 3, 1)         self.conv2 = nn.Conv2d(32, 64, 3, 1)         self.fc1 = nn.Linear(9216, 128)         self.fc2 = nn.Linear(128, 10)     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 = torch.flatten(x, 1)         x = self.fc1(x)         x = F.relu(x)         x = self.fc2(x)         return F.log_softmax(x, 1) # smdistributed: Define smp.step. Return any tensors needed outside. @smp.step def train_step(model, data, target):     output = model(data)     loss = F.nll_loss(output, target, reduction="mean")     model.backward(loss)     return output, loss def train(model, device, train_loader, optimizer):     model.train()     for batch_idx, (data, target) in enumerate(train_loader):         # smdistributed: Move input tensors to the GPU ID used by         # the current process, based on the set_device call.         data, target = data.to(device), target.to(device)         optimizer.zero_grad()         # Return value, loss_mb is a StepOutput object         _, loss_mb = train_step(model, data, target)         # smdistributed: Average the loss across microbatches.         loss = loss_mb.reduce_mean()         optimizer.step() # smdistributed: Initialize the backend smp.init() # smdistributed: Set the device to the GPU ID used by the current process. # Input tensors should be transferred to this device. torch.cuda.set_device(smp.local_rank()) device = torch.device("cuda") # smdistributed: Download only on a single process per instance. # When this is not present, the file is corrupted by multiple processes trying # to download and extract at the same time if smp.local_rank() == 0:     dataset = datasets.MNIST("../data", train=True, download=False) smp.barrier() # smdistributed: Shard the dataset based on data parallel ranks if smp.dp_size() > 1:     partitions_dict = {f"{i}": 1 / smp.dp_size() for i in range(smp.dp_size())}     dataset = SplitDataset(dataset, partitions=partitions_dict)     dataset.select(f"{smp.dp_rank()}") # smdistributed: Set drop_last=True to ensure that batch size is always divisible # by the number of microbatches train_loader = torch.utils.data.DataLoader(dataset, batch_size=64, drop_last=True) model = Net() # smdistributed: enable tensor parallelism only for model.fc1 smp.set_tensor_parallelism(model.fc1, True) # smdistributed: Use the DistributedModel container to provide the model # to be partitioned across different ranks. For the rest of the script, # the returned DistributedModel object should be used in place of # the model provided for DistributedModel class instantiation. model = smp.DistributedModel(model) optimizer = optim.AdaDelta(model.parameters(), lr=4.0) optimizer = smp.DistributedOptimizer(optimizer) train(model, device, train_loader, optimizer)