PennyLane 組み込みシミュレーターを使用してハイブリッドワークロードを実行する - Amazon Braket

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

PennyLane 組み込みシミュレーターを使用してハイブリッドワークロードを実行する

Amazon Braket Hybrid Jobs PennyLane で の埋め込みシミュレーターを使用してハイブリッドワークロードを実行する方法について説明します。Pennylane の GPUベースの組み込みシミュレーター はlightning.gpuNvidia cuQuantum ライブラリを使用して回路シミュレーションを加速します。埋め込みGPUシミュレーターは、ユーザーがすぐに使用できるすべての Braket ジョブコンテナに事前設定されています。このページでは、 lightning.gpu を使用してハイブリッドワークロードを高速化する方法を示します。

QAOA ワークロードlightning.gpuでの の使用

このノートブックの Quantum Approximate Optimization Algorithm (QAOA) の例を考えてみましょう。埋め込みシミュレータを選択するには、 形式の文字列となるdevice引数を指定します"local:<provider>/<simulator_name>"。例えば、 "local:pennylane/lightning.gpu"に を設定しますlightning.gpu。起動時にハイブリッドジョブに渡すデバイス文字列は、環境変数 としてジョブに渡されます"AMZN_BRAKET_DEVICE_ARN"

device_string = os.environ["AMZN_BRAKET_DEVICE_ARN"] prefix, device_name = device_string.split("/") device = qml.device(simulator_name, wires=n_wires)

このページでは、2 つの埋め込み PennyLane ステートベクトルシミュレータlightning.qubitー ( CPUベース) と lightning.gpu ( GPUベース) を比較してみましょう。さまざまな勾配を計算するには、シミュレーターにいくつかのカスタムゲート分解を提供する必要があります。

これで、ハイブリッドジョブ起動スクリプトの準備が整いました。QAOA アルゴリズムは、 m5.2xlargeと の 2 つのインスタンスタイプを使用して実行されますp3.2xlargem5.2xlarge インスタンスタイプは、標準のデベロッパーラップトップと同等です。p3.2xlarge は、16GB のメモリを持つ単一の NVIDIA Volta GPUを持つ高速コンピューティングインスタンスです。

すべてのハイブリッドジョブhyperparametersの は同じになります。さまざまなインスタンスとシミュレーターを試すために必要なのは、次のように 2 行変更することです。

# Specify device that the hybrid job will primarily be targeting device = "local:pennylane/lightning.qubit" # Run on a CPU based instance with about as much power as a laptop instance_config = InstanceConfig(instanceType='ml.m5.2xlarge')

または

# Specify device that the hybrid job will primarily be targeting device = "local:pennylane/lightning.gpu" # Run on an inexpensive GPU based instance instance_config = InstanceConfig(instanceType='ml.p3.2xlarge')
注記

GPUを ベースのインスタンスを使用して instance_config として指定し、埋め込み CPUベースのシミュレーター (lightning.qubit) deviceとして を選択した場合GPU、 は使用されません。をターゲットにする場合は、必ず埋め込み GPUベースのシミュレーターを使用してくださいGPU。

まず、2 つのハイブリッドジョブを作成し、18 個の頂点を持つグラフQAOAで を使用して Max-Cut を解決できます。これは 18 キュービット回路に変換されます。比較的小さく、ラップトップやm5.2xlargeインスタンスで迅速に実行できます。

num_nodes = 18 num_edges = 24 seed = 1967 graph = nx.gnm_random_graph(num_nodes, num_edges, seed=seed) # And similarly for the p3 job m5_job = AwsQuantumJob.create( device=device, source_module="qaoa_source", job_name="qaoa-m5-" + str(int(time.time())), image_uri=image_uri, # Relative to the source_module entry_point="qaoa_source.qaoa_algorithm_script", copy_checkpoints_from_job=None, instance_config=instance_config, # general parameters hyperparameters=hyperparameters, input_data={"input-graph": input_file_path}, wait_until_complete=True, )

m5.2xlarge インスタンスの平均反復時間は約 25 秒で、p3.2xlargeインスタンスの平均反復時間は約 12 秒です。この 18 キュービットワークフローでは、GPUインスタンスによって 2 倍の高速化が得られます。Amazon Braket Hybrid Jobs の料金ページを見るとm5.2xlargeインスタンスの 1 分あたりのコストは 0.00768 USD で、p3.2xlargeインスタンスの 1 分あたりのコストは 0.06375 USD であることがわかります。ここで行ったように、合計 5 回の反復を実行するには、 CPU インスタンスを使用して 0.016 USD または GPU インスタンスを使用して 0.06375 USD の費用がかかります。どちらもかなり安価です。

次に、問題をより困難にし、24 クォービットに変換される 24 頂点グラフで Max-Cut 問題を解決してみましょう。同じ 2 つのインスタンスでハイブリッドジョブを再度実行し、コストを比較します。

注記

CPU インスタンスでこのハイブリッドジョブを実行する時間は、約 5 時間になる場合があります。

num_nodes = 24 num_edges = 36 seed = 1967 graph = nx.gnm_random_graph(num_nodes, num_edges, seed=seed) # And similarly for the p3 job m5_big_job = AwsQuantumJob.create( device=device, source_module="qaoa_source", job_name="qaoa-m5-big-" + str(int(time.time())), image_uri=image_uri, # Relative to the source_module entry_point="qaoa_source.qaoa_algorithm_script", copy_checkpoints_from_job=None, instance_config=instance_config, # general parameters hyperparameters=hyperparameters, input_data={"input-graph": input_file_path}, wait_until_complete=True, )

m5.2xlarge インスタンスの平均反復時間は約 1 時間で、p3.2xlargeインスタンスの平均反復時間は約 2 分です。この大きな問題では、GPUインスタンスは桁違いの速度です。この高速化の恩恵を受けるために必要なのは、2 行のコードを変更し、インスタンスタイプと使用するローカルシミュレーターをスワップすることだけでした。ここで行ったように、合計 5 回の反復を実行するには、 CPU インスタンスを使用して約 $2.27072、または GPU インスタンスを使用して約 $0.775625 の費用がかかります。CPU 使用量はより高価であるだけでなく、実行により多くの時間がかかります。このワークフローを で使用可能なGPUインスタンスで高速化すると AWS、 にバックアップされた PennyLaneの埋め込みシミュレーターを使用してNVIDIA CuQuantum、中間量子ビット数 (20~30) のワークフローを実行することができ、総コストと時間を節約できます。つまり、ラップトップや同様のサイズのインスタンスですぐに実行できないほど大きな問題でも、量子コンピューティングを試すことができます。

量子機械学習とデータ並列処理

ワークロードタイプがデータセットでトレーニングする量子機械学習 (QML) の場合、データ並列処理を使用してワークロードをさらに高速化できます。ではQML、モデルには 1 つ以上の量子回路が含まれています。モデルには、クラシックニューラルネットが含まれる場合と含まれない場合があります。データセットを使用してモデルをトレーニングすると、モデル内のパラメータが更新され、損失関数が最小限に抑えられます。損失関数は通常、単一のデータポイントに対して定義され、データセット全体の平均損失の合計損失が定義されます。ではQML、通常、損失は勾配計算の合計損失を平均化する前に連続して計算されます。この手順は、特に数百のデータポイントがある場合に時間がかかります。

1 つのデータポイントからの損失は他のデータポイントに依存しないため、損失は並行して評価できます。異なるデータポイントに関連付けられた損失と勾配を同時に評価できます。これはデータ並列処理と呼ばれます。 SageMakerの分散データ並列ライブラリを使用すると、Amazon Braket Hybrid Jobs により、データ並列処理を活用してトレーニングを高速化しやすくなります。

二項分類の例として、有名なUCIリポジトリの Sonar データセットデータセットを使用するデータ並列処理では、次のQMLワークロードを考慮してください。Sonar データセットには 208 のデータポイントがあり、それぞれに 60 個の特徴があり、ソナーシグナルから収集され、マテリアルから跳ね返ります。各データポイントは、鉱山の場合は「M」、岩の場合は「R」というラベルが付けられます。当社のQMLモデルは、入力レイヤー、隠れレイヤーとしての量子回路、および出力レイヤーで構成されます。入力レイヤーと出力レイヤーは、 に実装されているクラシックニューラルネットです PyTorch。量子回路は、 PennyLaneの qml.qnn モジュールを使用して PyTorch ニューラルネットと統合されます。ワークロードの詳細については、ノートブックの例を参照してください。上記のQAOA例のように、 PennyLaneのような組み込みGPUの ベースのシミュレーターを使用してlightning.gpu、組み込みの CPUベースのシミュレーターよりもパフォーマンスを向上させるGPUことで、 のパワーを活用できます。

ハイブリッドジョブを作成するには、キーワード引数を使用してアルゴリズムスクリプト、デバイス、およびその他の設定を呼び出してAwsQuantumJob.create指定します。

instance_config = InstanceConfig(instanceType='ml.p3.2xlarge') hyperparameters={"nwires": "10", "ndata": "32", ... } job = AwsQuantumJob.create( device="local:pennylane/lightning.gpu", source_module="qml_source", entry_point="qml_source.train_single", hyperparameters=hyperparameters, instance_config=instance_config, ... )

データ並列処理を使用するには、 SageMaker 分散ライブラリのアルゴリズムスクリプト内のコード行数を変更して、トレーニングを正しく並列化する必要があります。まず、 smdistributedパッケージをインポートします。パッケージは、ワークロードを複数のGPUsインスタンスに分散するために、ほとんどの重量リフトを実行します。このパッケージは Braket PyTorch と TensorFlowコンテナで事前設定されています。このdistモジュールは、GPUsトレーニング (world_size) の合計数とGPUコアranklocal_rankの合計数をアルゴリズムスクリプトに伝えます。 rankはすべてのインスタンスGPUの の絶対インデックスで、 local_rank はインスタンスGPU内の のインデックスです。例えば、トレーニングにそれぞれ 8 がGPUs割り当てられているインスタンスが 4 つある場合、 rankの範囲は 0 ~ 31 で、 local_rankの範囲は 0 ~ 7 です。

import smdistributed.dataparallel.torch.distributed as dist dp_info = { "world_size": dist.get_world_size(), "rank": dist.get_rank(), "local_rank": dist.get_local_rank(), } batch_size //= dp_info["world_size"] // 8 batch_size = max(batch_size, 1)

次に、 world_sizeDistributedSamplerに従って を定義しrank、それをデータローダーに渡します。このサンプラーは、データセットの同じスライスGPUsへのアクセスを回避します。

train_sampler = torch.utils.data.distributed.DistributedSampler( train_dataset, num_replicas=dp_info["world_size"], rank=dp_info["rank"] ) train_loader = torch.utils.data.DataLoader( train_dataset, batch_size=batch_size, shuffle=False, num_workers=0, pin_memory=True, sampler=train_sampler, )

次に、 DistributedDataParallel クラスを使用してデータ並列処理を有効にします。

from smdistributed.dataparallel.torch.parallel.distributed import DistributedDataParallel as DDP model = DressedQNN(qc_dev).to(device) model = DDP(model) torch.cuda.set_device(dp_info["local_rank"]) model.cuda(dp_info["local_rank"])

上記は、データ並列処理を使用するために必要な変更です。ではQML、結果を保存し、トレーニングの進行状況を印刷することがよくあります。それぞれが保存コマンドと印刷コマンドGPUを実行すると、ログに繰り返し情報が溢れ、結果は互いに上書きされます。これを回避するには、0 rank GPUの からのみ保存および印刷できます。

if dp_info["rank"]==0: print('elapsed time: ', elapsed) torch.save(model.state_dict(), f"{output_dir}/test_local.pt") save_job_result({"last loss": loss_before})

Amazon Braket Hybrid Jobs は、 SageMaker 分散データ並列ライブラリのml.p3.16xlargeインスタンスタイプをサポートしています。Hybrid Jobs の InstanceConfig引数を使用してインスタンスタイプを設定します。 SageMaker 分散データ並列ライブラリがデータ並列処理が有効になっていることを知るには、 "sagemaker_distributed_dataparallel_enabled" を に設定"true"し、使用しているインスタンスタイプ"sagemaker_instance_type"に設定という 2 つのハイパーパラメータを追加する必要があります。これらの 2 つのハイパーパラメータはsmdistributedパッケージで使用されます。アルゴリズムスクリプトは明示的に使用する必要はありません。Amazon Braket ではSDK、便利なキーワード引数 を提供しますdistribution。ハイブリッドジョブの作成distribution="data_parallel"では、Amazon Braket は 2 つのハイパーパラメータSDKを自動的に挿入します。Amazon Braket を使用する場合はAPI、これら 2 つのハイパーパラメータを含める必要があります。

インスタンスとデータ並列処理を設定して、ハイブリッドジョブを送信できるようになりました。ml.p3.16xlarge インスタンスGPUsには 8 つあります。を設定するとinstanceCount=1、ワークロードはインスタンスGPUsの 8 に分散されます。instanceCount 複数の を設定すると、ワークロードはすべてのインスタンスGPUsで使用できる に分散されます。複数のインスタンスを使用する場合、各インスタンスの使用時間に基づいて料金が発生します。例えば、4 つのインスタンスを使用する場合、ワークロードを同時に実行しているインスタンスが 4 つあるため、請求対象時間はインスタンスあたりの実行時間の 4 倍になります。

instance_config = InstanceConfig(instanceType='ml.p3.16xlarge', instanceCount=1, ) hyperparameters={"nwires": "10", "ndata": "32", ..., } job = AwsQuantumJob.create( device="local:pennylane/lightning.gpu", source_module="qml_source", entry_point="qml_source.train_dp", hyperparameters=hyperparameters, instance_config=instance_config, distribution="data_parallel", ... )
注記

上記のハイブリッドジョブの作成では、 train_dp.pyはデータ並列処理を使用するための変更されたアルゴリズムスクリプトです。データ並列処理は、上記のセクションに従ってアルゴリズムスクリプトを変更する場合にのみ正しく機能することに注意してください。データ並列処理オプションが正しく変更されていないと、ハイブリッドジョブがエラーをスローしたり、それぞれが同じデータスライスを繰り返し処理GPUしたりすることがあります。これは非効率です。

上記の二項分類の問題に対して、26 クォータの量子回路でモデルをトレーニングする場合の例では、実行時間とコストを比較してみましょう。この例ではml.p3.16xlarge、1 分あたり 0.4692 ドルのインスタンスを使用します。データ並列処理がない場合、シミュレーターは 1 エポック (208 を超えるデータポイント) でモデルをトレーニングするのに約 45 分かかり、コストは約 20 ドルです。1 つのインスタンスと 4 つのインスタンスのデータ並列処理では、それぞれ 6 分と 1.5 分しかかからず、どちらも約 2.8 ドルになります。4 つのインスタンスでデータ並列処理を使用すると、実行時間を 30 倍向上させるだけでなく、コストを 1 桁削減できます。