

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

# Amazon Braket Hybrid Jobs の使用方法
<a name="braket-jobs"></a>

Amazon Braket Hybrid Jobs は、古典的な AWS リソースと量子処理ユニット (QPUs) の両方を必要とするハイブリッド量子古典アルゴリズムを実行する方法を提供します。Hybrid Jobs は、リクエストされた古典的リソースを起動し、アルゴリズムを実行し、完了後にインスタンスを解放するように設計されているため、*使用量*に対してのみ料金が発生します。

Hybrid Jobs は、古典コンピューティングリソースと量子コンピューティングリソースの両方を使用する、長時間実行される反復アルゴリズムに最適です。Hybrid Jobs を使用する場合、実行するアルゴリズムを送信すると、アルゴリズムは、Braket により、スケーラブルでコンテナ化された環境で実行されます。アルゴリズムが完了したら、結果を取得できます。

さらに、ハイブリッドジョブから作成された量子タスクは、ターゲットとなる QPU デバイスへのキューイングにおいて優先順位が高くなるという利点があります。この優先順位付けにより、送信した量子コンピューティングが処理され、キューで待機している他のタスクよりも前に実行されます。これは、1 つの量子タスクの結果が以前の量子タスクの結果に依存する反復ハイブリッドアルゴリズムの場合に特に利点があります。このようなアルゴリズムの例としては、[量子近似最適化アルゴリズム (QAOA)](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_quantum_algorithms/QAOA/QAOA_braket.ipynb)、[変分量子固有値ソルバー](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_quantum_algorithms/VQE_Chemistry/VQE_chemistry_braket.ipynb)、[量子機械学習](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/1_Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs/Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs.ipynb)などがあります。また、アルゴリズムの進行状況をほぼリアルタイムでモニタリングできるため、コスト、予算、および、トレーニング損失やトレーニング期待値などのカスタムメトリクスを追跡できます。

Braket のハイブリッドジョブには、以下を使用してアクセスできます。
+ [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python)。
+ [Amazon Braket コンソール](https://console.aws.amazon.com/braket/home)。
+ Amazon Braket API。

**Topics**
+ [Amazon Braket Hybrid Jobs を使用すべき場合](#braket-jobs-use)
+ [Amazon Braket Hybrid Jobs でハイブリッドジョブを実行する](#braket-jobs-works)
+ [ハイブリッドジョブの主要なコンセプト](braket-jobs-concepts.md)
+ [前提条件](braket-jobs-prerequisites.md)
+ [ハイブリッドジョブの作成](braket-jobs-first.md)
+ [ハイブリッドジョブのキャンセル](braket-jobs-cancel.md)
+ [ハイブリッドジョブのカスタマイズ](braket-jobs-customize.md)
+ [PennyLane と Amazon Braket の併用](hybrid.md)
+ [CUDA-Q と Amazon Braket の併用方法](braket-using-cuda-q.md)

## Amazon Braket Hybrid Jobs を使用すべき場合
<a name="braket-jobs-use"></a>

 Amazon Braket Hybrid Jobs を使用すると、古典的なコンピューティングリソースと量子コンピューティングデバイスを組み合わせて、今日の量子系のパフォーマンスを最適化する、変分量子固有ソルバー (VQE) や量子近似最適化アルゴリズム (QAOA) などのハイブリッド量子古典アルゴリズムを実行できます。Amazon Braket Hybrid Jobs には、主に次の 3 つの利点があります。

1.  **パフォーマンス**: Amazon Braket Hybrid Jobs は、お客様の環境からハイブリッドアルゴリズムを実行するよりも優れたパフォーマンスを提供します。ハイブリッドジョブは、実行中に、選択したターゲット QPU に優先的にアクセスできます。ハイブリッドジョブ内のタスクは、デバイスでキューに入っている他のタスクよりも先に実行されます。これにより、ハイブリッドアルゴリズムの実行時間が短くなり、予測しやすくなります。また、Amazon Braket Hybrid Jobs は、パラメトリックコンパイルもサポートしています。自由パラメータを使用して回路を送信できるため、Braket は回路を 1 回コンパイルするだけです。同じ回路に対する後続のパラメータ更新を再コンパイルする必要がないため、実行時間がはるかに短縮されます。

1.  **利便性**: Amazon Braket Hybrid Jobs は、コンピューティング環境のセットアップと管理を簡素化し、ハイブリッドアルゴリズムの実行中も実行し続けることができます。アルゴリズムスクリプトを提供し、実行する量子デバイス (量子処理装置またはシミュレーター) を選択するだけでよいのです。Amazon Braket は、ターゲットデバイスが利用可能になるまで待機し、古典リソースを起動し、構築済みのコンテナ環境でワークロードを実行し、Amazon Simple Storage Service (Amazon S3) に結果を返し、コンピューティングリソースを解放します。

1.  **メトリクス**: Amazon Braket Hybrid Jobs は、実行中のアルゴリズムに関するオンザフライのインサイトを提供し、カスタマイズ可能なアルゴリズムメトリクスをほぼリアルタイムで Amazon CloudWatch と Amazon Braket コンソールに配信することで、アルゴリズムの進行状況を追跡できます。

## Amazon Braket Hybrid Jobs でハイブリッドジョブを実行する
<a name="braket-jobs-works"></a>

Amazon Braket Hybrid Jobs でハイブリッドジョブを実行するには、まずアルゴリズムを定義する必要があります。[Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) または [PennyLane](https://pennylane.ai) を使用して、*アルゴリズムスクリプト*と、オプションで他の依存関係ファイルを作成することで定義できます。他の (オープンソースまたはプロプライエタリ) ライブラリを使用する場合は、それらのライブラリが含まれている Docker を使用することで、独自のカスタムコンテナイメージを定義できます。詳細については、「[自分のコンテナを持参 (BYOC)](braket-jobs-byoc.md)」を参照してください。

いずれの場合も、次に Amazon Braket API を使用してジョブを作成します。ここで、アルゴリズムスクリプトまたはコンテナを指定し、ハイブリッドジョブが使用するターゲット量子デバイスを選択し、さまざまなオプション設定から選択します。これらのオプション設定で提供されているデフォルト値は、ほとんどのユースケースで機能します。ターゲットデバイスにハイブリッドジョブを実行させる場合、QPU、オンデマンドシミュレーター (SV1、DM1、TN1 など)、または古典的なハイブリッドジョブインスタンス自体のいずれかを選択できます。オンデマンドシミュレーターまたは QPU を選択する場合は、ハイブリッドジョブコンテナはリモートデバイスに API コールを行います。埋め込みシミュレーターを選択する場合は、シミュレーターがアルゴリズムスクリプトと同じコンテナに埋め込まれます。PennyLane の[稲妻シミュレーター](https://github.com/PennyLaneAI/pennylane-lightning)には、デフォルトの構築済みハイブリッドジョブコンテナが埋め込まれています。埋め込み PennyLane シミュレーターまたはカスタムシミュレーターを使用してコードを実行する場合は、インスタンスタイプ、および使用するインスタンスの数を指定できます。各選択肢にかかるコストについては、[Amazon Braket の料金ページ](https://aws.amazon.com/braket/pricing/)を参照してください。

![\[ユーザーがハイブリッドタスク、QPU タスク、オンデマンドタスク、埋め込みタスクのために、Amazon Braket コンポーネント、API、ジョブインスタンス、シミュレーターに対して行う操作を示すフローチャート図。結果は Amazon Simple Storage Service バケットに保存され、Amazon Braket コンソールで Amazon CloudWatch を使用して分析されます。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-hybrid-job-run.png)


ターゲットデバイスがオンデマンドシミュレーターまたは埋め込みシミュレーターの場合、Amazon Braket はハイブリッドジョブの実行をすぐに開始します。ハイブリッドジョブインスタンスがスピンアップされて (API コールでインスタンスタイプをカスタマイズできます) アルゴリズムが実行され、結果が Amazon S3 に書き込まれてリソースが解放されます。このリソースの解放により、使用した分に対してのみお支払いいただくだけで済むようになります。

量子処理ユニット (QPU) あたりの同時ハイブリッドジョブの合計数は制限されています。現在、一度に QPU で実行できるハイブリッドジョブは 1 つのみです。許可される制限を超えないよう、実行できるハイブリッドジョブの数を制御するために、キューが使用されます。ターゲットデバイスが QPU の場合、ハイブリッドジョブは選択した QPU の*ジョブキュー*に最初に入ります。Amazon Braket は、必要なハイブリッドジョブインスタンスを起動し、ハイブリッドジョブをデバイスで実行します。アルゴリズムの期間中、ハイブリッドジョブには優先アクセスがあります。つまり、ハイブリッドジョブの量子タスクが数分に 1 回 QPU に送信されている場合、ジョブの量子タスクはデバイスでキューに入れられた他の Braket 量子タスクよりも先に実行されます。ハイブリッドジョブが完了すると、リソースが解放されるため、使用した分に対してのみ料金が発生します。

**注記**  
デバイスはリージョン別であり、ハイブリッドジョブはプライマリデバイス AWS リージョン と同じ で実行されます。

シミュレーターおよび QPU の両方のターゲットシナリオで、アルゴリズムの一部としてハミルトニアンのエネルギーなどのカスタムアルゴリズムメトリクスを定義するオプションがあります。これらのメトリクスは Amazon CloudWatch に自動的にレポートされ、そこからほぼリアルタイムに Amazon Braket コンソールに表示されます。

**注記**  
GPU ベースのインスタンスを使用する場合は、Braket の埋め込みシミュレーターとともに使用できるいずれかの GPU ベースシミュレーター (例えば `lightning.gpu` など) を使用してください。いずれかの CPU ベース埋め込みシミュレーター (例えば `lightning.qubit` や `braket:default-simulator` など) を選択した場合、GPU が使用されないため、不要なコストが発生する可能性があります。

# ハイブリッドジョブの主要なコンセプト
<a name="braket-jobs-concepts"></a>

このセクションでは、Amazon Braket Python SDK によって指定される `AwsQuantumJob.create` 関数の主要なコンセプトと、コンテナファイル構造へのマッピングを説明します。

ハイブリッドジョブには、アルゴリズムスクリプト全体を構成する 1 つまたは複数のファイルに加えて、追加の入力と出力を含めることができます。ハイブリッドジョブが開始されると、Amazon Braket はハイブリッドジョブ作成の一部として指定された入力を、アルゴリズムスクリプトを実行するコンテナにコピーします。ハイブリッドジョブが完了すると、アルゴリズムで定義されたすべての出力が、指定された Amazon S3 の場所にコピーされます。

**注記**  
 *アルゴリズムメトリクス*はリアルタイムで報告されますので、この出力手順に従わないでください。

Amazon Braket では、コンテナの入力と出力とのやりとりを簡素化するために、いくつかの環境変数とヘルパー関数も指定します。詳細については、「*Amazon Braket SDK*」の「[braket.jobs package](https://amazon-braket-sdk-python.readthedocs.io/en/latest/_apidoc/braket.jobs.html)」を参照してください。

**Topics**
+ [入力](#braket-jobs-inputs)
+ [アウトプット](#braket-jobs-outputs)
+ [環境変数](#braket-jobs-environmental-variables)
+ [ヘルパー関数](#braket-jobs-helper-functions)

## 入力
<a name="braket-jobs-inputs"></a>

 **入力データ**: 入力データをハイブリッドアルゴリズムに提供するには、ディクショナリとして設定されている入力データファイルを `input_data` 引数に指定します。ユーザーは引数 `input_data` を SDK の `AwsQuantumJob.create` 関数内に定義します。この引数により、環境変数 `"AMZN_BRAKET_INPUT_DIR"` で指定された場所にあるコンテナファイルシステムに入力データがコピーされます。ハイブリッドアルゴリズムでの入力データの使用方法のいくつかの例については、「[QAOA with Amazon Braket Hybrid Jobs and PennyLane](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/2_Using_PennyLane_with_Braket_Hybrid_Jobs/Using_PennyLane_with_Braket_Hybrid_Jobs.ipynb)」および「[Quantum machine learning in Amazon Braket Hybrid Jobs](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/1_Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs/Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs.ipynb)」Jupyter Notebook を参照してください。

**注記**  
入力データが大きい (>1GB) 場合、ハイブリッドジョブが送信されるまでの待機時間が長くなります。これは、最初にローカル入力データが S3 バケットにアップロードされ、次に S3 パスがハイブリッドジョブリクエストに追加されて、最後にハイブリッドジョブリクエストが Braket サービスに送信されるためです。

 **ハイパーパラメータ**: `hyperparameters` を入力として渡した場合は、環境変数 `"AMZN_BRAKET_HP_FILE"` に設定されます。

**注記**  
ハイパーパラメータと入力データを作成し、この情報をハイブリッドジョブスクリプトに渡す方法の詳細については、「[ハイパーパラメータの使用](braket-jobs-hyperparameters.md)」セクションと[こちらの github ページ](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/1_Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs/qcbm/qcbm.py)を参照してください。

 **チェックポイント**: 新しいハイブリッドジョブでチェックポイントを使用する `job-arn` を指定するには、`copy_checkpoints_from_job` コマンドを使用します。このコマンドは、チェックポイントデータを新しいハイブリッドジョブの `checkpoint_configs3Uri` にコピーし、ジョブの実行中に、環境変数 `AMZN_BRAKET_CHECKPOINT_DIR` で指定されたパスで使用できるようにします。デフォルトは、`None` であり、別のハイブリッドジョブからのチェックポイントデータが新しいハイブリッドジョブでは使用されないことを意味します。

## アウトプット
<a name="braket-jobs-outputs"></a>

 **量子タスク**: 量子タスクの結果は S3 の場所 `s3://amazon-braket-<region>-<accountID>/jobs/<job-name>/tasks`に 保存されます。

 **ジョブの結果**: アルゴリズムスクリプトが環境変数 `"AMZN_BRAKET_JOB_RESULTS_DIR"` で指定されたディレクトリに保存するものはすべて、`output_data_config` で指定された S3 の場所にコピーされます。この場所の値が指定されない場合のデフォルト値は、`s3://amazon-braket-<region>-<accountID>/jobs/<job-name>/<timestamp>/data` です。SDK ヘルパー関数 ** `save_job_result` ** が用意されています。これをアルゴリズムスクリプトから呼び出すと、結果を簡単にディクショナリ形式で保存できます。

 **チェックポイント**: チェックポイントを使用する場合は、環境変数 `"AMZN_BRAKET_CHECKPOINT_DIR"` で指定されたディレクトリに保存できます。代わりに、SDK ヘルパー関数 `save_job_checkpoint` を使用することもできます。

 **アルゴリズムメトリクス**: Amazon CloudWatch に放出され、ハイブリッドジョブの実行中に Amazon Braket コンソールにリアルタイムで表示されるアルゴリズムスクリプトの一部が、アルゴリズムメトリクスの定義です。アルゴリズムメトリクスの使用方法の例については、「[Use Amazon Braket Hybrid Jobs to run a QAOA algorithm](braket-jobs-run-qaoa-algorithm.md)」を参照してください。

ジョブ出力の保存の詳細については、Hybrid Jobs ドキュメントの「[Save your results](https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs-first.html#braket-jobs-save-results)」を参照してください。

## 環境変数
<a name="braket-jobs-environmental-variables"></a>

Amazon Braket は、コンテナの入力と出力の操作を簡素化するために、いくつかの環境変数を指定しています。次のコードは、Braket が使用する環境変数の一覧です。
+ `AMZN_BRAKET_INPUT_DIR` – 入力データディレクトリ opt/braket/input/data。
+ `AMZN_BRAKET_JOB_RESULTS_DIR` – ジョブ結果を書き込む出力ディレクトリ opt/braket/model。
+ `AMZN_BRAKET_JOB_NAME` – ジョブの名前。
+ `AMZN_BRAKET_CHECKPOINT_DIR` – チェックポイントディレクトリ。
+ `AMZN_BRAKET_HP_FILE` – ハイパーパラメータを格納するファイル。
+ `AMZN_BRAKET_DEVICE_ARN` – デバイス ARN (AWS リソース名）。
+ `AMZN_BRAKET_OUT_S3_BUCKET` – `CreateJob` リクエストの `OutputDataConfig` で指定する出力 Amazon S3 バケット。
+ `AMZN_BRAKET_SCRIPT_ENTRY_POINT` – `CreateJob` リクエストの `ScriptModeConfig` で指定するエントリポイント。
+ `AMZN_BRAKET_SCRIPT_COMPRESSION_TYPE` – `CreateJob`リクエストの `ScriptModeConfig` で指定する圧縮タイプ。
+ `AMZN_BRAKET_SCRIPT_S3_URI` – `CreateJob`リクエストの `ScriptModeConfig` で指定する、ユーザースクリプトを保管する Amazon S3 の場所。
+ `AMZN_BRAKET_TASK_RESULTS_S3_URI` – SDK がジョブの量子タスクの結果をデフォルトで保存する Amazon S3 の場所。
+ `AMZN_BRAKET_JOB_RESULTS_S3_PATH` – `CreateJob` リクエストの `OutputDataConfig` で指定する、ジョブ結果を保存する Amazon S3 の場所。
+ `AMZN_BRAKET_JOB_TOKEN` – ジョブコンテナ内に作成される量子タスクのための、`CreateQuantumTask` の `jobToken` パラメータに渡される文字列。

## ヘルパー関数
<a name="braket-jobs-helper-functions"></a>

Amazon Braket には、コンテナの入出力とのやりとりを簡素化するためのいくつかのヘルパー関数が指定されています。これらのヘルパー関数は、ハイブリッドジョブの実行に使用されるアルゴリズムスクリプト内から呼び出されます。次の例は、その使用方法を示しています。

```
from braket.jobs import get_checkpoint_dir, get_hyperparameters, get_input_data_dir, get_job_device_arn, get_job_name, get_results_dir, save_job_result, save_job_checkpoint, load_job_checkpoint

get_checkpoint_dir() # Get the checkpoint directory
get_hyperparameters() # Get the hyperparameters as strings
get_input_data_dir() # Get the input data directory
get_job_device_arn() # Get the device specified by the hybrid job
get_job_name() # Get the name of the hybrid job.
get_results_dir() # Get the path to a results directory
save_job_result(result_data='data') # Save hybrid job results
save_job_checkpoint(checkpoint_data={'key': 'value'}) # Save a checkpoint
load_job_checkpoint() # Load a previously saved checkpoint
```

# 前提条件
<a name="braket-jobs-prerequisites"></a>

最初のハイブリッドジョブを実行する前に、このタスクを続行するための十分なアクセス許可があることを確認してください。適切なアクセス許可があることを確認するには、Braket コンソールの左側にあるメニューから **[アクセス許可]** を選択します。**[Amazon Braket のアクセス許可管理]** ページでは、既存のロールの 1 つでジョブの実行に十分な権限があるかどうかを確認したり、そのようなロールをまだ持っていない場合にジョブの実行に使用できるデフォルトロールの作成方法について説明しています。

![\[Hybrid Jobs 実行ロールの既存ロールを確認できるように、サービスにリンクされたロールとオプションを表示する、Amazon Braket サービスのアクセス許可と設定ページ。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-permissions.png)


ハイブリッドジョブを実行するための十分なアクセス許可を持つロールがあることを確認するには、**[既存のロールを検証]** ボタンを選択します。選択すると、ロールが見つかったというメッセージが表示されます。ロールの名前とそのロール ARN を表示するには、**[ロールを表示]** ボタンを選択します。

![\[見つかったサービスリンクロールと、ハイブリッドジョブを実行するのに十分なアクセス許可を持つ既存のロールを表示している、Amazon Braket のアクセス許可と設定画面。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-permissions-verify-yes.png)


ハイブリッドジョブを実行するのに十分な権限を持つロールがない場合は、そのようなロールが見つからなかったというメッセージが表示されます。**[デフォルトのロールの作成]** ボタンを選択して、十分な権限を持つロールを取得します。

![\[サービスにリンクされたロールは見つかったが、ハイブリッドジョブの実行ロールが見つからなかったことを示す、Amazon Braket のアクセス許可と設定ページ。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-permissions-verify-no.png)


ロールが正常に作成された場合は、これを確認するメッセージが表示されます。

![\[サービスにリンクされたロールが見つかるとともにハイブリッドジョブの実行ロールが正常に作成されたことを示す、Amazon Braket のアクセス許可と設定ページ。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-permissions-verify-created.png)


この問い合わせを行う権限がない場合、アクセスは拒否されます。この場合、内部 AWS 管理者にお問い合わせください。

![\[ユーザーが AmazonBraketJobsExecutionRole で iam:ListAttachedRolePolicies を実行する権限がないことを明示的な拒否によって示している AccessDenied エラーメッセージ。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-permissions-access-denied.png)


# ハイブリッドジョブの作成
<a name="braket-jobs-first"></a>

 このセクションでは、Python スクリプトを使用してハイブリッドジョブを作成する方法を示します。または、ハイブリッドジョブを作成する別の方法として任意の統合開発環境 (IDE) や Braket ノートブックなどのローカル Python コードを使用する手順については、「[ローカルコードをハイブリッドジョブとして実行する](braket-hybrid-job-decorator.md)」を参照してください。

**Topics**
+ [作成して実行](#braket-jobs-first-create)
+ [結果をモニタリングする](#braket-jobs-first-monitor-results)
+ [結果を保存する](#braket-jobs-save-results)
+ [チェックポイントの使用](#braket-jobs-checkpoints)
+ [ローカルコードをハイブリッドジョブとして実行する](braket-hybrid-job-decorator.md)
+ [ハイブリッドジョブでの API の使用方法](braket-jobs-api.md)
+ [ローカルモードでのハイブリッドジョブの作成およびデバッグ](braket-jobs-local-mode.md)

## 作成して実行
<a name="braket-jobs-first-create"></a>

ハイブリッドジョブを実行する権限を持つロールを取得したら、次に進む準備が整ったことになります。最初の Braket ハイブリッドジョブの重要部分は、*アルゴリズムスクリプト*です。実行するアルゴリズムを定義し、アルゴリズムの一部である古典的な論理と量子タスクが含まれています。アルゴリズムスクリプトに加えて、他の依存関係ファイルを指定することもできます。アルゴリズムスクリプトとその依存関係は、*ソースモジュール*と呼ばれます。*エントリポイント*は、ハイブリッドジョブの開始時にソースモジュールで実行される最初のファイルまたは関数を定義します。

![\[コンソールまたはノートブックを使用して量子ジョブを作成し、量子デバイスでアルゴリズムスクリプトを実行し、結果を分析するワークフローを示した図。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-workflow.jpg)


まず、5 つのベル状態を作成し、対応する測定結果を出力するアルゴリズムスクリプトの基本的な例を考えてみましょう。

```
import os

from braket.aws import AwsDevice
from braket.circuits import Circuit


def start_here():

    print("Test job started!")

    # Use the device declared in the job script
    device = AwsDevice(os.environ["AMZN_BRAKET_DEVICE_ARN"])

    bell = Circuit().h(0).cnot(0, 1)
    for count in range(5):
        task = device.run(bell, shots=100)
        print(task.result().measurement_counts)

    print("Test job completed!")
```

このファイルを*algorithm\$1script.py* という名前で、Braket ノートブックまたはローカル環境の現在の作業ディレクトリに保存します。algorithm\$1script.py ファイルには計画されたエントリーポイントとして `start_here()` が含まれます。

次に、algorithm\$1script.py ファイルと同じディレクトリに Python ファイルまたは Python ノートブックを作成します。このスクリプトは、ハイブリッドジョブを開始し、必要なステータスや主要な結果の出力などの非同期処理を扱っています。このスクリプトでは、少なくともハイブリッドジョブスクリプトとプライマリデバイスを指定する必要があります。

**注記**  
Braket ノートブックを作成する方法、または *algorithm\$1script.py* ファイルなどのファイルをノートブックと同じディレクトリにアップロードする方法の詳細については、「[Run your first circuit using the Amazon Braket Python SDK](braket-get-started-run-circuit.md)」を参照してください。

この基本的な最初のケースでは、シミュレーターをターゲットにします。ターゲットとする量子デバイス、シミュレーター、または実際の量子処理装置 (QPU) のいずれのタイプであっても、次のスクリプトでは、`device` でハイブリッドジョブをスケジュールするために使用され、アルゴリズムスクリプトで環境変数 `AMZN_BRAKET_DEVICE_ARN` として使用できます。

**注記**  
ハイブリッドジョブ AWS リージョン の で使用できるデバイスのみを使用できます。Amazon Braket SDK はこの AWS リージョンを自動的に選択します。例えば、us-east-1 のハイブリッドジョブでは、IonQ、SV1、DM1、および TN1 デバイスを使用できますが、Rigetti デバイスは使用できません。

シミュレーターの代わりに量子コンピュータを選択した場合、Braket は優先アクセスですべての量子タスクを実行するようにハイブリッドジョブをスケジュールします。

```
from braket.aws import AwsQuantumJob
from braket.devices import Devices

job = AwsQuantumJob.create(
    Devices.Amazon.SV1,
    source_module="algorithm_script.py",
    entry_point="algorithm_script:start_here",
    wait_until_complete=True
)
```

パラメータ `wait_until_complete=True` は、冗長モードを設定して、ジョブが実行中に実際のジョブからの出力を出力するようにします。以下の例のような出力が表示されます。

```
Initializing Braket Job: arn:aws:braket:us-west-2:111122223333:job/braket-job-default-123456789012
Job queue position: 1
Job queue position: 1
Job queue position: 1
..............
.
.
.
Beginning Setup
Checking for Additional Requirements
Additional Requirements Check Finished
Running Code As Process
Test job started!
Counter({'00': 58, '11': 42})
Counter({'00': 55, '11': 45})
Counter({'11': 51, '00': 49})
Counter({'00': 56, '11': 44})
Counter({'11': 56, '00': 44})
Test job completed!
Code Run Finished
2025-09-24 23:13:40,962 sagemaker-training-toolkit INFO     Reporting training SUCCESS
```

**注記**  
[AwsQuantumJob.create](https://amazon-braket-sdk-python.readthedocs.io/en/latest/_apidoc/braket.aws.aws_quantum_job.html#braket.aws.aws_quantum_job.AwsQuantumJob.create) メソッドを使用してカスタムメイドのモジュールを実行するには、その場所 (ローカルディレクトリまたはファイルへのパス、または tar.gz ファイルの S3 URI) を渡します。実例については、「[Amazon Braket examples](https://github.com/amazon-braket/amazon-braket-examples/tree/main)」Github リポジトリの hybrid jobs フォルダにある [Parallelize\$1training\$1for\$1QML.ipynb](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/5_Parallelize_training_for_QML/Parallelize_training_for_QML.ipynb) ファイルを参照してください。

## 結果をモニタリングする
<a name="braket-jobs-first-monitor-results"></a>

または、Amazon CloudWatch からのログ出力にアクセスすることもできます。これを行うには､ジョブ詳細ページの左側のメニューにある **[ロググループ]** タブに移動し、ロググループ `aws/braket/jobs` をクリックして、ジョブ名を含むログストリームを選択します。これは、上記の例では `braket-job-default-1631915042705/algo-1-1631915190` です。

![\[Amazon Braket SDK Python テストのファイルパスとタイムスタンプを含むログイベントのリストを示す CloudWatch ロググループ。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-cw-log.png)


また、コンソールでハイブリッドジョブのステータスを表示するには、**[ハイブリッドジョブ]** ページを選択して **[設定]** を選択します。

![\[要約、イベント時間、ソースコードとインスタンスの設定、停止条件が表示されている、Amazon Braket ハイブリッドジョブの詳細。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-jobs-first-console-status.png)


ハイブリッドジョブが実行されている間、Amazon S3 にアーティファクトがいくつか生成されます。デフォルトの S3 バケット名は `amazon-braket-<region>-<accountid>` で、コンテンツは `jobs/<jobname>/<timestamp>` ディレクトリにあります。Braket Python SDK でハイブリッドジョブを作成する際、別の `code_location` を指定することで、これらのアーティファクトが保存される S3 の場所を設定できます。

**注記**  
この S3 バケットは、ジョブスクリプト AWS リージョン と同じ に配置する必要があります。

`jobs/<jobname>/<timestamp>` ディレクトリには、`model.tar.gz` ファイル内のエントリポイントスクリプトからの出力を含むサブフォルダが含まれています。`script` というディレクトリもあり、この中にある `source.tar.gz` ファイルにはアルゴリズムスクリプトのアーティファクトが含まれています。実際の量子タスクの結果は、`jobs/<jobname>/tasks` という名前のディレクトリにあります。

## 結果を保存する
<a name="braket-jobs-save-results"></a>

アルゴリズムスクリプトによって生成された結果を保存することで、ハイブリッドジョブスクリプトのハイブリッドジョブオブジェクトと Amazon S3 の出力フォルダ (model.tar.gz という名前の tar zip ファイル内) からそれらを使用できるようにすることができます。

出力は JavaScript Object Notation (JSON) 形式を使用してファイルに保存する必要があります。numpy 配列の場合のように、データをテキストに簡単にシリアル化できない場合は、ピクル化データ形式を使用してシリアル化するオプションを入力として渡すことができます。詳細については、「[braket.jobs.data\$1persistence module](https://amazon-braket-sdk-python.readthedocs.io/en/latest/_apidoc/braket.jobs.data_persistence.html#braket.jobs.data_persistence.save_job_result)」を参照してください。

ハイブリッドジョブの結果を保存するには、\$1ADD でコメントされた次の行を algorithm\$1script.py ファイルに追加します。

```
import os

from braket.aws import AwsDevice
from braket.circuits import Circuit
from braket.jobs import save_job_result  # ADD


def start_here():

    print("Test job started!")

    device = AwsDevice(os.environ['AMZN_BRAKET_DEVICE_ARN'])

    results = []  # ADD

    bell = Circuit().h(0).cnot(0, 1)
    for count in range(5):
        task = device.run(bell, shots=100)
        print(task.result().measurement_counts)
        results.append(task.result().measurement_counts)  # ADD

        save_job_result({"measurement_counts": results})  # ADD

    print("Test job completed!")
```

次に、\$1ADD でコメントされた行 ** `print(job.result())` ** を追加することで、ジョブスクリプトのジョブの結果を表示できます。

```
import time
from braket.aws import AwsQuantumJob

job = AwsQuantumJob.create(
    source_module="algorithm_script.py",
    entry_point="algorithm_script:start_here",
    device="arn:aws:braket:::device/quantum-simulator/amazon/sv1",
)

print(job.arn)
while job.state() not in AwsQuantumJob.TERMINAL_STATES:
    print(job.state())
    time.sleep(10)

print(job.state())
print(job.result())   # ADD
```

この例では、`wait_until_complete=True` を削除して冗長出力を抑制します。デバッグ用に再度追加できます。このハイブリッドジョブを実行すると、識別子と `job-arn` が出力され、その後、10 秒ごとにハイブリッドジョブの状態が出力されて、ハイブリッドジョブが `COMPLETED` になったら、ベル回路の結果が示されます。次の例を参照してください。

```
arn:aws:braket:us-west-2:111122223333:job/braket-job-default-123456789012
INITIALIZED
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
RUNNING
...
RUNNING
RUNNING
COMPLETED
{'measurement_counts': [{'11': 53, '00': 47},..., {'00': 51, '11': 49}]}
```

## チェックポイントの使用
<a name="braket-jobs-checkpoints"></a>

チェックポイントを使用して、ハイブリッドジョブの中間イテレーションを保存できます。前のセクションのアルゴリズムスクリプトの例では、\$1ADD でコメントされた次の行を追加して、チェックポイントファイルを作成します。

```
from braket.aws import AwsDevice
from braket.circuits import Circuit
from braket.jobs import save_job_checkpoint  # ADD
import os


def start_here():

    print("Test job starts!")

    device = AwsDevice(os.environ["AMZN_BRAKET_DEVICE_ARN"])

    # ADD the following code
    job_name = os.environ["AMZN_BRAKET_JOB_NAME"]
    save_job_checkpoint(checkpoint_data={"data": f"data for checkpoint from {job_name}"}, checkpoint_file_suffix="checkpoint-1")  # End of ADD

    bell = Circuit().h(0).cnot(0, 1)
    for count in range(5):
        task = device.run(bell, shots=100)
        print(task.result().measurement_counts)

    print("Test hybrid job completed!")
```

ハイブリッドジョブを実行すると、デフォルトの `/opt/jobs/checkpoints` パスを使用して、チェックポイントディレクトリのハイブリッドジョブアーティファクトにファイル *<jobname>-checkpoint-1.json* が作成されます。このデフォルトパスを変更しない限り、ハイブリッドジョブスクリプトは変更されません。

前のハイブリッドジョブによって生成されたチェックポイントからハイブリッドジョブをロードする場合、アルゴリズムスクリプトは `from braket.jobs import load_job_checkpoint` を使用します。アルゴリズムスクリプトにロードするロジックは次のとおりです。

```
from braket.jobs import load_job_checkpoint

checkpoint_1 = load_job_checkpoint(
    "previous_job_name",
    checkpoint_file_suffix="checkpoint-1",
)
```

このチェックポイントをロードした後、`checkpoint-1` にロードされたコンテンツに基づいてロジックを続行できます。

**注記**  
*checkpoint\$1file\$1suffix* は、チェックポイントの作成時に以前に指定した接尾辞と一致する必要があります。

オーケストレーションスクリプトでは、前のハイブリッドジョブ `job-arn` を、\$1ADD でコメントされた行で指定する必要があります。

```
from braket.aws import AwsQuantumJob

job = AwsQuantumJob.create(
    source_module="source_dir",
    entry_point="source_dir.algorithm_script:start_here",
    device="arn:aws:braket:::device/quantum-simulator/amazon/sv1",
    copy_checkpoints_from_job="<previous-job-ARN>", #ADD
    )
```

# ローカルコードをハイブリッドジョブとして実行する
<a name="braket-hybrid-job-decorator"></a>

Amazon Braket Hybrid Jobs は、ハイブリッド量子古典アルゴリズムのフルマネージドオーケストレーションを提供し、Amazon EC2 コンピューティングリソースと Amazon Braket 量子処理ユニット (QPU) アクセスを統合します。ハイブリッドジョブで作成された量子タスクは、個々の量子タスクよりも優先的にキューイングされるため、量子タスクキュー内の変動によってアルゴリズムが中断されることはありません。各 QPU は独自のハイブリッドジョブキューを維持することで、ハイブリッドジョブを一度に 1 つだけ実行するようにします。

**Topics**
+ [ローカル Python コードからハイブリッドジョブを作成する](#create-hybrid-job-from-local-python-code)
+ [追加の Python パッケージとソースコードをインストールする](#install-python-packages-and-code)
+ [ハイブリッドジョブインスタンスにおいてデータをロードしたり保存したりする](#save-load-data-into-instance)
+ [ハイブリッドジョブデコレータに関するベストプラクティス](#best-practices)

## ローカル Python コードからハイブリッドジョブを作成する
<a name="create-hybrid-job-from-local-python-code"></a>

ローカル Python コードを Amazon Braket Hybrid Jobs として実行できます。これは、次のコードサンプルに示すように、コードに `@hybrid_job` デコレータで注釈を付けることで実現できます。カスタム環境では、Amazon Elastic Container Registry (ECR) の[カスタムコンテナの使用](braket-jobs-byoc.md)を選択できます。

**注記**  
デフォルトでは、Python 3.12 のみがサポートされています。

 `@hybrid_job` デコレータを使用して関数に注釈を付けることができます。Braket は、デコレータ内のコードを Braket ハイブリッドジョブの[アルゴリズムスクリプト](braket-jobs-first.md)に変換します。次に、ハイブリッドジョブは Amazon EC2 インスタンス上で被デコレート関数を呼び出します。ジョブの進行状況は、`job.state()` または Braket コンソールでモニタリングできます。次のコード例は、State Vector Simulator (SV1) device で 5 つの状態のシーケンスを実行する方法を示しています。

```
from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter, Observable
from braket.devices import Devices
from braket.jobs.hybrid_job import hybrid_job
from braket.jobs.metrics import log_metric

device_arn = Devices.Amazon.SV1


@hybrid_job(device=device_arn)  # Choose priority device
def run_hybrid_job(num_tasks=1):
    device = AwsDevice(device_arn)  # Declare AwsDevice within the hybrid job

    # Create a parametric circuit
    circ = Circuit()
    circ.rx(0, FreeParameter("theta"))
    circ.cnot(0, 1)
    circ.expectation(observable=Observable.X(), target=0)

    theta = 0.0  # Initial parameter

    for i in range(num_tasks):
        task = device.run(circ, shots=100, inputs={"theta": theta})  # Input parameters
        exp_val = task.result().values[0]

        theta += exp_val  # Modify the parameter (possibly gradient descent)

        log_metric(metric_name="exp_val", value=exp_val, iteration_number=i)

    return {"final_theta": theta, "final_exp_val": exp_val}
```

ハイブリッドジョブを作成するには、通常の Python 関数と同様に被デコレート関数を呼び出します。ただし、デコレータ関数は、被デコレート関数の結果ではなくハイブリッドジョブのハンドルを返します。ジョブの完了後に結果を取得するには、`job.result()` を使用します。

```
job = run_hybrid_job(num_tasks=1)
result = job.result()
```

`@hybrid_job` デコレータのデバイス引数には、ハイブリッドジョブが優先アクセス権を持つデバイスを指定します。この場合はシミュレーター SV1 です。QPU の優先順位を取得するには、デコレータで指定されたものと一致するデバイス ARN を被デコレート関数内で使用する必要があります。`@hybrid_job` で宣言されたデバイス ARN をキャプチャするには、ヘルパー関数 `get_job_device_arn()` を使用するという便利な方法もあります。

**注記**  
各ハイブリッドジョブが Amazon EC2 上にコンテナ化された環境を作成してから起動するまでに、1 分以上かかります。このため、単一の回路や回路のバッチなど、非常に短いワークロードでは、量子タスクを使用するだけで十分です。

**ハイパーパラメータ** 

`run_hybrid_job()` 関数が取る引数として、作成される量子タスクの数を制御できる `num_tasks` があります。ハイブリッドジョブは、この引数を[ハイパーパラメータ](braket-jobs-hyperparameters.md)として自動的にキャプチャします。

**注記**  
ハイパーパラメータは、文字列として Braket コンソールに表示されますが、2500 文字の制限があります。

**メトリクスとログ記録** 

`run_hybrid_job()` 関数内では、反復アルゴリズムからのメトリクスが `log_metrics` を使用して記録されます。メトリクスは、Braket コンソールページのハイブリッドジョブタブに自動的にプロットされます。[Braket コストトラッカー](braket-pricing.md)を使用することで、ハイブリッドジョブ実行中の量子タスクのコストをほぼリアルタイムで追跡できます。上記の例では、[結果タイプ](braket-result-types.md)における最初の確率を記録するメトリクス名「probability」(確率) を使用しています。

**結果を取得する** 

ハイブリッドジョブが完了したら、 `job.result()` を使用することで、ハイブリッドジョブの結果を取得できます。return ステートメントに記述したすべてのオブジェクトが、Braket によって自動的にキャプチャされます。関数が返すオブジェクトは、各要素がシリアル化可能なタプルである必要があります。例えば、次のコードは成功している例と失敗している例を示しています。

```
import numpy as np


# Working example
@hybrid_job(device=Devices.Amazon.SV1)
def passing():
    np_array = np.random.rand(5)
    return np_array  # Serializable

# # Failing example
# @hybrid_job(device=Devices.Amazon.SV1)
# def failing():
#     return MyObject() # Not serializable
```

**ジョブ名** 

デフォルトでは、このハイブリッドジョブの名前は関数名を使用して提案されます。また、50 文字までの長さのカスタム名を指定することもできます。例えば、次のコードでは、ジョブ名は「my-job-name」です。

```
@hybrid_job(device=Devices.Amazon.SV1, job_name="my-job-name")
def function():
    pass
```

**ローカルモード** 

[ローカルジョブ](braket-jobs-local-mode.md)は、デコレータに引数 `local=True` を追加することで作成されます。これにより、ラップトップなどのローカルコンピューティング環境のコンテナ化された環境でハイブリッドジョブが実行されます。ローカルジョブでは、量子タスクに対して優先的なキューイングが行われることは**ありません**。マルチノードや MPI などの高度なケースでは、ローカルジョブが、必要な Braket 環境変数にアクセスできる場合があります。次のコードは、SV1 シミュレーターをデバイスとして使用してローカルハイブリッドジョブを作成しています。

```
@hybrid_job(device=Devices.Amazon.SV1, local=True)
def run_hybrid_job(num_tasks=1):
    return ...
```

この他にも、あらゆるハイブリッドジョブオプションがサポートされています。オプションのリストについては、「[braket.jobs.quantum\$1job\$1creation module](https://amazon-braket-sdk-python.readthedocs.io/en/stable/_apidoc/braket.jobs.quantum_job_creation.html)」を参照してください。

## 追加の Python パッケージとソースコードをインストールする
<a name="install-python-packages-and-code"></a>

希望の Python パッケージを使用できるようにランタイム環境をカスタマイズできます。パッケージ名のリストである `requirements.txt` ファイルか、[独自のコンテナ (BYOC)](braket-jobs-byoc.md) のいずれかを使用できます。例えば、`requirements.txt` ファイルには、インストールが必要な他のパッケージを含めることができます。

```
qiskit 
pennylane >= 0.31
mitiq == 0.29
```

`requirements.txt` ファイルを使用してランタイム環境をカスタマイズするには、以下のコード例を参照してください。

```
@hybrid_job(device=Devices.Amazon.SV1, dependencies="requirements.txt")
def run_hybrid_job(num_tasks=1):
    return ...
```

または、次のようにパッケージ名を Python リストとして指定することもできます。

```
@hybrid_job(device=Devices.Amazon.SV1, dependencies=["qiskit", "pennylane>=0.31", "mitiq==0.29"])
def run_hybrid_job(num_tasks=1):
    return ...
```

追加のソースコードは、モジュールのリストとして指定することも、次のコード例のように単一のモジュールとして指定することもできます。

```
@hybrid_job(device=Devices.Amazon.SV1, include_modules=["my_module1", "my_module2"])
def run_hybrid_job(num_tasks=1):
    return ...
```

## ハイブリッドジョブインスタンスにおいてデータをロードしたり保存したりする
<a name="save-load-data-into-instance"></a>

**入力トレーニングデータを指定する**

ハイブリッドジョブを作成する場合は、Amazon Simple Storage Service (Amazon S3) バケットを指定して入力トレーニングデータセットを提供できます。また、ローカルパスを指定すれば、データが Braket によって Amazon S3 の `s3://<default_bucket_name>/jobs/<job_name>/<timestamp>/data/<channel_name>` に自動的にアップロードされます。ローカルパスを指定した場合、チャネル名はデフォルトで「input」になります。次のコードは、ローカルパス `data/file.npy` からアップロードされた numpy ファイルを示しています。

```
import numpy as np


@hybrid_job(device=Devices.Amazon.SV1, input_data="data/file.npy")
def run_hybrid_job(num_tasks=1):
    data = np.load("data/file.npy")
    return ...
```

S3 の場合は、`get_input_data_dir()` ヘルパー関数を使用する必要があります。

```
import numpy as np
from braket.jobs import get_input_data_dir

s3_path = "s3://amazon-braket-us-east-1-123456789012/job-data/file.npy"


@hybrid_job(device=None, input_data=s3_path)
def job_s3_input():
    np.load(get_input_data_dir() + "/file.npy")


@hybrid_job(device=None, input_data={"channel": s3_path})
def job_s3_input_channel():
    np.load(get_input_data_dir("channel") + "/file.npy")
```

チャネル値と S3 URI またはローカルパスで構成されるディクショナリを提供することで、複数の入力データソースを指定できます。

```
import numpy as np
from braket.jobs import get_input_data_dir

input_data = {
    "input": "data/file.npy",
    "input_2": "s3://amzn-s3-demo-bucket/data.json"
}


@hybrid_job(device=None, input_data=input_data)
def multiple_input_job():
    np.load(get_input_data_dir("input") + "/file.npy")
    np.load(get_input_data_dir("input_2") + "/data.json")
```

**注記**  
入力データが大きい (>1GB) 場合、ハイブリッドジョブが作成されるまでの待機時間が長くなります。これは、ローカル入力データが最初に S3 バケットにアップロードされた時点で S3 パスがジョブリクエストに追加されるためです。つまり、ジョブリクエストが Braket サービスに送信されのが最後であるためです。

**結果を S3 に保存する**

被デコレート関数の return ステートメントに指定されていない結果を保存するには、すべてのファイル書き込みオペレーションに正しいディレクトリを追加する必要があります。次の例は、numpy 配列と matplotlib 図の保存を示しています。

```
import matplotlib.pyplot as plt
import numpy as np


@hybrid_job(device=Devices.Amazon.SV1)
def run_hybrid_job(num_tasks=1):
    result = np.random.rand(5)

    # Save a numpy array
    np.save("result.npy", result)

    # Save a matplotlib figure
    plt.plot(result)
    plt.savefig("fig.png")
    return ...
```

すべての結果は `model.tar.gz` という名前のファイルに圧縮されます。この結果をダウンロードするには、Python 関数 `job.result()` を使用するか、または Braket マネジメントコンソールのハイブリッドジョブページにある結果フォルダに移動します。

**チェックポイントからの保存と再開**

長時間実行されるハイブリッドジョブの場合、アルゴリズムの中間状態を定期的に保存することをお勧めします。組み込みの `save_job_checkpoint()` ヘルパー関数を使用するか、ファイルを `AMZN_BRAKET_JOB_RESULTS_DIR` パスに保存できます。後者のパスはヘルパー関数 `get_job_results_dir()` で使用できます。

以下は、最小限の作業によって、ハイブリッドジョブデコレータを使用してチェックポイントを保存およびロードする例です。

```
from braket.jobs import save_job_checkpoint, load_job_checkpoint, hybrid_job


@hybrid_job(device=None, wait_until_complete=True)
def function():
    save_job_checkpoint({"a": 1})


job = function()
job_name = job.name
job_arn = job.arn


@hybrid_job(device=None, wait_until_complete=True, copy_checkpoints_from_job=job_arn)
def continued_function():
    load_job_checkpoint(job_name)


continued_job = continued_function()
```

最初のハイブリッドジョブでは、 `save_job_checkpoint()` が、保存するデータを含むディクショナリを指定して呼び出されています。デフォルトでは、すべての値がテキストとしてシリアル化されます。numpy 配列など、より複雑な Python オブジェクトのチェックポイントファイルを作成するには、`data_format = PersistedJobDataFormat.PICKLED_V4` を設定します。このコードは、「checkpoints」というサブフォルダにあるハイブリッドジョブアーティファクトに、デフォルト名 `<jobname>.json` を持つチェックポイントファイルを作成および上書きします。

チェックポイントから再開する新しいハイブリッドジョブを作成するには、`copy_checkpoints_from_job=job_arn` を渡す必要があります。ここで、`job_arn` は直前のジョブのハイブリッドジョブ ARN です。次に、`load_job_checkpoint(job_name)` を使用してチェックポイントの内容をロードします。

## ハイブリッドジョブデコレータに関するベストプラクティス
<a name="best-practices"></a>

**非同期性を採用する**

デコレータ注釈を使用して作成されたハイブリッドジョブは、古典的リソースと量子リソースが利用可能になると実行され、非同期です。アルゴリズムの進行状況をモニタリングするには、Braket Management Console または Amazon CloudWatch を使用します。実行すべきアルゴリズムを送信すると、Braket により、スケーラブルなコンテナ化された環境で実行され、完了すると結果が取得されます。

**反復変分アルゴリズムを実行する**

ハイブリッドジョブでは、反復量子古典アルゴリズムを実行するツールを使用できます。純粋に量子力学的な問題には、[量子タスク](braket-submit-tasks.md)または[量子タスクのバッチ](braket-batching-tasks.md)を使用します。特定の QPU への優先的なアクセスは、古典的な処理で QPU への複数の反復呼び出しを断続的に必要とする、長時間実行される変分アルゴリズムに最も有益です。

**ローカルモードを使用してデバッグする**

QPU でハイブリッドジョブを実行する場合は、まずシミュレーター SV1 で実行して、期待どおりに実行されるかを確認することをお勧めします。小規模なテストでは、ローカルモードで実行することで迅速な反復実行とデバッグを行うことができます。

[独自のコンテナ (BYOC)](braket-jobs-byoc.md) により再現性を向上する

コンテナ化された環境内にソフトウェアとその依存関係をカプセル化することで、再現可能な実験を作成します。すべてのコード、依存関係、設定をコンテナにパッケージ化することで、潜在的な競合やバージョニングの問題を回避できます。

**マルチインスタンス分散シミュレーター**

多数の回路を実行するには、組み込みの MPI サポートを使用して、単一のハイブリッドジョブにおいて、複数のインスタンスでローカルシミュレーターを実行することを検討してください。詳細については、「[embedded simulators](pennylane-embedded-simulators.md)」を参照してください。

**パラメトリック回路を使用する**

ハイブリッドジョブから送信したパラメトリック回路は、[パラメトリックコンパイル](braket-jobs-parametric-compilation.md)を使用して特定の QPU で自動的にコンパイルされるため、アルゴリズムの実行時間が短縮されます。

**定期的にチェックポイントを作成する**

長時間実行されるハイブリッドジョブの場合、アルゴリズムの中間状態を定期的に保存することをお勧めします。

**その他の例、ユースケース、ベストプラクティスについては、GitHub の「[Amazon Braket examples](https://github.com/amazon-braket/amazon-braket-examples)」を参照してください。**

# ハイブリッドジョブでの API の使用方法
<a name="braket-jobs-api"></a>

API を直接使用することで、Amazon Braket Hybrid Jobs にアクセスして操作できます。ただし、API を直接使用する場合にはデフォルトおよび便利なメソッドは使用できなくなります。

**注記**  
Amazon Braket Hybrid Jobs の操作には [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) を使用することを強くお勧めします。ハイブリッドジョブが正常に実行されるようにする便利なデフォルトと保護が提供されているためです。

このトピックでは、API の基本的な使用方法について説明します。API を使用するというアプローチは、SDK を使用する場合よりも複雑になることに注意してください。ハイブリッドジョブを実行できるようになるまでに、何度も試行錯誤する覚悟が必要です。

API を使用するには、アカウントに、`AmazonBraketFullAccess` マネージドポリシーを持つロールが必要です。

**注記**  
`AmazonBraketFullAccess` マネージドポリシーでロールを取得する方法の詳細については、「[Amazon Braket を有効にする](braket-enable-overview.md)」ページを参照してください。

また、**実行ロール**も必要です。このロールはサービスに渡されます。このロールを作成するには、**Amazon Braket コンソール**を使用します。**[アクセス許可と設定]** ページの **[実行ロール]** タブを使用して、ハイブリッドジョブのデフォルトロールを作成できます。

`CreateJob` API では、ハイブリッドジョブに必要なパラメータをすべて指定する必要があります。Python を使用するには、input.tar.gz ファイルなどのアルゴリズムスクリプトファイルを tar バンドルに圧縮し、次のスクリプトを実行します。コードのうち山括弧 (`<>`) で囲まれた部分を更新して、ハイブリッドジョブを開始するパス、ファイル、メソッドを指定するアカウント情報およびエントリポイントに一致させます。

```
from braket.aws import AwsDevice, AwsSession
import boto3
from datetime import datetime

s3_client = boto3.client("s3")
client = boto3.client("braket")

project_name = "job-test"
job_name = project_name + "-" + datetime.strftime(datetime.now(), "%Y%m%d%H%M%S")
bucket = "amazon-braket-<your_bucket>"
s3_prefix = job_name

job_script = "input.tar.gz"
job_object = f"{s3_prefix}/script/{job_script}"
s3_client.upload_file(job_script, bucket, job_object)

input_data = "inputdata.csv"
input_object = f"{s3_prefix}/input/{input_data}"
s3_client.upload_file(input_data, bucket, input_object)

job = client.create_job(
    jobName=job_name,
    roleArn="arn:aws:iam::<your_account>:role/service-role/AmazonBraketJobsExecutionRole",  # https://docs.aws.amazon.com/braket/latest/developerguide/braket-manage-access.html#about-amazonbraketjobsexecution
    algorithmSpecification={
        "scriptModeConfig": {
            "entryPoint": "<your_execution_module>:<your_execution_method>",
            "containerImage": {"uri": "292282985366.dkr.ecr.us-west-1.amazonaws.com/amazon-braket-base-jobs:1.0-cpu-py37-ubuntu18.04"},   # Change to the specific region you are using
            "s3Uri": f"s3://{bucket}/{job_object}",
            "compressionType": "GZIP"
        }
    },
    inputDataConfig=[
        {
            "channelName": "hellothere",
            "compressionType": "NONE",
            "dataSource": {
                "s3DataSource": {
                    "s3Uri": f"s3://{bucket}/{s3_prefix}/input",
                    "s3DataType": "S3_PREFIX"
                }
            }
        }
    ],
    outputDataConfig={
        "s3Path": f"s3://{bucket}/{s3_prefix}/output"
    },
    instanceConfig={
        "instanceType": "ml.m5.large",
        "instanceCount": 1,
        "volumeSizeInGb": 1
    },
    checkpointConfig={
        "s3Uri":  f"s3://{bucket}/{s3_prefix}/checkpoints",
        "localPath": "/opt/omega/checkpoints"
    },
    deviceConfig={
        "priorityAccess": {
            "devices": [
                "arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3"
            ]
        }
    },
    hyperParameters={
        "hyperparameter key you wish to pass": "<hyperparameter value you wish to pass>",
    },
    stoppingCondition={
        "maxRuntimeInSeconds": 1200,
        "maximumTaskLimit": 10
    },
)
```

ハイブリッドジョブの作成後に、ハイブリッドジョブの詳細にアクセスするには、`GetJob` API またはコンソールを使用します。直前の例のように `createJob` コードを実行した Python セッションからハイブリッドジョブの詳細を取得するには、次の Python コマンドを使用します。

```
getJob = client.get_job(jobArn=job["jobArn"])
```

ハイブリッドジョブをキャンセルするには、ジョブ ('JobArn') の <noloc>Amazon リソースネーム</noloc>を指定して `CancelJob` API を呼び出します。

```
cancelJob = client.cancel_job(jobArn=job["jobArn"])
```

チェックポイントを指定するには、`createJob` API の一部として `checkpointConfig` パラメータを使用します。

```
    checkpointConfig = {
        "localPath" : "/opt/omega/checkpoints",
        "s3Uri": f"s3://{bucket}/{s3_prefix}/checkpoints"
    },
```

**注記**  
`checkpointConfig` のローカルパスの先頭を、予約済みパスである `/opt/ml`、`/opt/braket`、`/tmp`、または `/usr/local/nvidia` のいずれかにすることはできません。

# ローカルモードでのハイブリッドジョブの作成およびデバッグ
<a name="braket-jobs-local-mode"></a>

新しいハイブリッドアルゴリズムを構築する際、ローカルモードはアルゴリズムスクリプトのデバッグとテストに役立ちます。ローカルモードは、Amazon Braket Hybrid Jobs で使用する予定のコードを実行できる機能ですが、Braket がハイブリッドジョブを実行するためのインフラストラクチャを管理する必要はありません。代わりに、Amazon Braket ノートインスタンスまたはノートブックパソコンやデスクトップコンピュータなどの優先クライアントでハイブリッドジョブをローカルで実行します。

ローカルモードでは、量子タスクを実際のデバイスに送信することはできますが、ローカルモードで実際の量子処理ユニット (QPU) に対して実行すると、パフォーマンス上の利点は得られません。

ローカルモードを使用するには、プログラム内で AwsQuantumJob が使用されている箇所で、`AwsQuantumJob` を `LocalQuantumJob` に変更します。例えば、「[最初のジョブを作成する](braket-jobs-first.md)」に記載されている例を実行するには、コード内のハイブリッドジョブスクリプトを次のように編集します。

```
from braket.jobs.local import LocalQuantumJob

job = LocalQuantumJob.create(
    device="arn:aws:braket:::device/quantum-simulator/amazon/sv1",
    source_module="algorithm_script.py",
    entry_point="algorithm_script:start_here",
)
```

**注記**  
この機能を使用するには、Amazon Braket ノートブックに既にプリインストールされている Docker をローカル環境にインストールする必要があります。Docker のインストール手順については、「[Get Docker](https://docs.docker.com/get-started/get-docker/)」ページを参照してください。また、ローカルモードではすべてのパラメータがサポートされているわけではありません。

# ハイブリッドジョブのキャンセル
<a name="braket-jobs-cancel"></a>

最終ステータス以外のハイブリッドジョブをキャンセルすることが必要になる場合があります。これは、コンソールまたはコードで行うことができます。

コンソールでハイブリッドジョブをキャンセルするには、**[ハイブリッドジョブ]** ページからキャンセルするハイブリッドジョブを選択し、**[アクション]** ドロップダウンメニューから **[ハイブリッドジョブをキャンセル]** を選択します。

![\[名前、ステータス、デバイス情報、タイムスタンプを示した 4 つのジョブを含む Amazon Braket ハイブリッドジョブテーブル。[アクション] ドロップダウンには、新しいハイブリッドジョブの表示、キャンセル、タグの管理を行うオプションが含まれています。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-hybrid-cancel-job.png)


キャンセルを確定するには、プロンプトが表示されたら入力フィールドに「*cancel*」と入力し、**[OK]** を選択します。

![\[特定のジョブをキャンセルするダイアログボックス (キャンセルプロセスに関する警告あり) と、「cancel」と入力して確定するためのテキスト入力フィールド。\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/images/braket-hybrid-cancel-job-confirm.png)


Braket Python SDK のコードを使用してハイブリッドジョブをキャンセルするには、`job_arn` を使用してハイブリッドジョブを特定し、次のコードに示すように `cancel` コマンドを呼び出します。

```
job = AwsQuantumJob(arn=job_arn)
job.cancel()
```

`cancel` コマンドは、ハイブリッドジョブの古典側コンテナを直ちに終了し、まだ最終ステータスに到達していない関連量子タスクをすべて、ベストエフォート方式でキャンセルします。

# ハイブリッドジョブのカスタマイズ
<a name="braket-jobs-customize"></a>

Amazon Braket には、ハイブリッドジョブの実行方法をカスタマイズするいくつかの方法が用意されており、特定のニーズに合わせて環境を調整できます。このセクションでは、アルゴリズムスクリプト環境の定義から独自のコンテナまで、ハイブリッドジョブをカスタマイズできるオプションについて説明します。ハイパーパラメータを使用したワークフローの最適化、ジョブインスタンスの設定、およびパラメトリックコンパイルを活用したパフォーマンスの向上を行う方法について説明します。これらのカスタマイズ手法は、Amazon Braket でのハイブリッド量子計算の潜在能力を最大限引き出すのに役立ちます。

**Topics**
+ [アルゴリズムスクリプトの環境を定義する](braket-jobs-script-environment.md)
+ [ハイパーパラメータの使用方法](braket-jobs-hyperparameters.md)
+ [ハイブリッドジョブインスタンスの設定](braket-jobs-configure-job-instance-for-script.md)
+ [パラメトリックコンパイルを使用したハイブリッドジョブの高速化](braket-jobs-parametric-compilation.md)

# アルゴリズムスクリプトの環境を定義する
<a name="braket-jobs-script-environment"></a>

Amazon Braket は、アルゴリズムスクリプトのコンテナによって定義された環境をサポートしています。
+ ベースコンテナ (`image_uri` が指定されていない場合のデフォルト)
+ CUDA-Q のコンテナ
+ Tensorflow と PennyLane のコンテナ
+ PyTorch、PennyLane、CUDA-Q のコンテナ

次の表に、コンテナとその付属ライブラリの詳細を示します。


**Amazon Braket コンテナ**  

| タイプ | ベース | CUDA-Q | TensorFlow | PyTorch | 
| --- | --- | --- | --- | --- | 
|   **イメージ URI**   |  292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-base-jobs:latest  |  292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-cudaq-jobs:latest  |  292282985366.dkr.ecr.us-east-1.amazonaws.com/amazon-braket-tensorflow-jobs:latest  |  292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-pytorch-jobs:latest  | 
|   **継承ライブラリ**   |  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  | 
|   **追加のライブラリ**   |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  |  [\[See the AWS documentation website for more details\]](http://docs.aws.amazon.com/ja_jp/braket/latest/developerguide/braket-jobs-script-environment.html)  | 

オープンソースのコンテナ定義は、[aws/amazon-braket-containers](https://github.com/aws/amazon-braket-containers) で確認およびアクセスできます。ユースケースに一致するコンテナを選択します。Braket で使用可能な AWS リージョン (us-east-1、us-west-1、us-west-2、eu-north-1、eu-west-2) のいずれかを使用できますが、コンテナリージョンはハイブリッドジョブのリージョンと一致する必要があります。ハイブリッドジョブを作成する際、次の 3 つの引数のいずれかをハイブリッドジョブスクリプトの `create(…​)` コールに追加することでコンテナイメージを指定します。Amazon Braket コンテナはインターネット接続を備えているため、実行時に選択したコンテナに追加の依存関係を (起動時間または実行時間を犠牲にして) インストールできます。次の例は、us-west-2 リージョンの場合です。
+  **ベースイメージ:** image\$1uri"292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-base-jobs:latest"
+  **CUDA-Q イメージ:** image\$1uri"292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-cudaq-jobs:latest"
+  **Tensorflow イメージ:** image\$1uri="292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-tensorflow-jobs:latest"
+  **PyTorch イメージ:** image\$1uri="292282985366.dkr.ecr.us-west-2.amazonaws.com/amazon-braket-pytorch-jobs:latest"

また、`image-uris` は、Amazon Braket SDK の `retrieve_image()` 関数を使用して取得することもできます。次の例は、us-west-2 からそれらを取得する方法を示しています AWS リージョン。

```
from braket.jobs.image_uris import retrieve_image, Framework

image_uri_base = retrieve_image(Framework.BASE, "us-west-2")
image_uri_cudaq = retrieve_image(Framework.CUDAQ, "us-west-2")
image_uri_tf = retrieve_image(Framework.PL_TENSORFLOW, "us-west-2")
image_uri_pytorch = retrieve_image(Framework.PL_PYTORCH, "us-west-2")
```

# 独自のコンテナ (BYOC)
<a name="braket-jobs-byoc"></a>

Amazon Braket Hybrid Jobs には、さまざまな環境でコードを実行するための 3 つの構築済みコンテナが用意されています。これらのコンテナの 1 つがユースケースをサポートしている場合は、ハイブリッドジョブを作成するときにアルゴリズムスクリプトを指定するだけで済みます。`pip` を使用して `requirements.txt` ファイルから、またはアルゴリズムスクリプトから、欠落している小さな依存関係を追加できます。

これらのコンテナがユースケースをサポートしていない場合、またはそれらを拡張したい場合、Braket Hybrid Jobs は、独自のカスタム Docker コンテナイメージまたは独自のコンテナ (BYOC) を使用したハイブリッドジョブの実行をサポートします。それがユースケースに適した機能であることを確認してください。

**Topics**
+ [独自のコンテナは、どのような場合に適した選択肢となりますか?](#bring-own-container-decision)
+ [独自のコンテナのレシピ](bring-own-container-recipe.md)
+ [独自のコンテナでの Braket ハイブリッドジョブの実行](running-hybrid-jobs-in-own-container.md)

## 独自のコンテナは、どのような場合に適した選択肢となりますか?
<a name="bring-own-container-decision"></a>

Braket Hybrid Jobs で独自のコンテナ (BYOC) を使用すると、パッケージ化された環境に独自のソフトウェアをインストールして利用できる柔軟性が得られます。お客様のニーズによっては、同じ柔軟性を実現できる方法があります。そのような場合、「BYOC Docker を構築して Amazon ECR にアップロードし、カスタムイメージ URI を取得する」という完全なサイクルを経る必要がありません。

**注記**  
公開されている少数の Python パッケージ (通常は 10 未満) を追加する場合は、BYOC が適した選択肢にならない場合があります。例えば、PyPi を使用する場合です。

この場合、構築済みの Braket イメージのいずれかを使用し、ジョブ送信時にソースディレクトリに `requirements.txt` ファイルを含めることができます。このファイルが自動的に読み込まれ、`pip` により、パッケージが指定されたバージョンで正常にインストールされます。多数のパッケージをインストールする場合、ジョブの実行時間が大幅に長くなる可能性があります。Python を確認します。また、必要に応じて、ソフトウェアが動作するかどうかをテストするために使用する構築済みコンテナの CUDA バージョンを確認します。

BYOC が必要になるのは、ジョブスクリプトに Python 以外の言語 (C\$1\$1 や Rust など) を使用する場合や、Braket の構築済みコンテナでは利用できない Python バージョンを使用する場合です。BYOC は、次の場合にも適した選択肢です。
+ ソフトウェアをライセンスキーで使用するため、そのソフトウェアを実行するのにライセンスサーバーに対するそのキーの認証が必要となる場合。BYOC を使用を使用してライセンスキーを Docker イメージに埋め込むことで、ソフトウェアの認証コードを含めることができます。
+ 公開されていないソフトウェアを使用する場合。例えば、ソフトウェアが、アクセスするのに特定の SSH キーが必要なプライベートな GitLab または GitHub リポジトリでホストされている場合などです。
+ Braket が提供するコンテナにパッケージ化されていない大規模なソフトウェアスイートをインストールする必要がある場合。ソフトウェアのインストールによってハイブリッドジョブコンテナの起動時間が長くなるのを、BYOC の使用によって回避できます。

また、BYOC では、ソフトウェアを含んだ Docker コンテナを構築し、それを各ユーザーが利用できるようにすることで、カスタムの SDK またはアルゴリズムを各ユーザーが利用できるようにします。これを行うには、Amazon ECR で適切なアクセス許可を設定します。

**注記**  
該当するすべてのソフトウェアライセンスの条項を遵守する必要があります。

# 独自のコンテナのレシピ
<a name="bring-own-container-recipe"></a>

このセクションでは、Braket Hybrid Jobs に bring your own container (BYOC) を持ち込むために必要なもの、つまりスクリプト、ファイル、および、それらを組み合わせてカスタム Docker イメージを起動して実行するための手順を順を追って説明します。2 つの代表的なケースに対するレシピ:

1. Docker イメージに追加のソフトウェアをインストールし、ジョブ内で Python アルゴリズムスクリプトのみを使用するケース。

1. Python 以外の言語で記述されたアルゴリズムスクリプトと Hybrid Jobs を使用するか、x86 以外の CPU アーキテクチャを使用するケース。

ケース 2 では、*コンテナエントリスクリプト*の定義がより複雑になります。

Braket は、ハイブリッドジョブを実行する際、リクエストされた数とタイプの Amazon EC2 インスタンスを起動し、それらのインスタンス上でジョブ作成へのイメージ URI 入力で指定された Docker イメージを実行します。BYOC 機能を使用する場合は、読み取りアクセス権がある[プライベート Amazon ECR リポジトリ](https://docs.aws.amazon.com/AmazonECR/latest/userguide/Repositories.html)でホストされているイメージ URI を指定します。Braket Hybrid Jobs は、当該のカスタムイメージを使用してジョブを実行します。

Hybrid Jobs で使用できる Docker イメージを構築するには、特定のコンポーネントが必要です。`Dockerfiles` の記述と構築に慣れていない場合は、「[Dockerfile documentation](https://docs.docker.com/reference/dockerfile/)」と「[Amazon ECR CLI documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html)」を参照してください。

**Topics**
+ [Dockerfile のベースイメージ](#base-image-dockerfile)
+ [(オプション) 変更されたコンテナエントリポイントスクリプト](#modified-container-entry-point)
+ [`Dockerfile` を使用して必要なソフトウェアとコンテナスクリプトをインストールする](#install-docketfile)

## Dockerfile のベースイメージ
<a name="base-image-dockerfile"></a>

Python を使用し、Braket が提供するコンテナにソフトウェアをインストールする場合、ベースイメージの選択肢としては、[GitHub リポジトリ](https://github.com/amazon-braket/amazon-braket-containers)と Amazon ECR でホストされている Braket コンテナイメージの 1 つがあります。イメージをプルしてその上に構築するには、[Amazon ECR に対して認証](https://docs.aws.amazon.com/AmazonECR/latest/userguide/getting-started-cli.html#cli-authenticate-registry)する必要があります。例えば、BYOC Docker ファイルの最初の行は次のように指定できます: `FROM [IMAGE_URI_HERE]`。

次に、Dockerfile の残りの部分に入力することで、コンテナに追加するソフトウェアをインストールして設定します。構築済みの Braket イメージには既に適切なコンテナエントリポイントスクリプトが含まれているため、あらためて含める必要はありません。

C\$1\$1、Rust、Julia など Python 以外の言語を使用する場合、または ARM など x86 以外の CPU アーキテクチャ用のイメージを構築する場合は、ベアボーンパブリックイメージ上に構築する必要がある場合があります。このようなイメージを [Amazon Elastic Container Registry Public Gallery](https://gallery.ecr.aws/) で数多く見つけることができます。CPU アーキテクチャに適切 (であるとともに、必要に応じて使用する GPU にも適切) なイメージを必ず選択してください。

## (オプション) 変更されたコンテナエントリポイントスクリプト
<a name="modified-container-entry-point"></a>

**注記**  
構築済みの Braket イメージにソフトウェアを追加するだけの場合は、このセクションをスキップできます。

ハイブリッドジョブの一部として Python 以外のコードを実行するには、コンテナエントリポイントを定義する Python スクリプトを変更します。例として、[`braket_container.py`Amazon Braket Github の Python スクリプト](https://github.com/amazon-braket/amazon-braket-containers/blob/main/src/braket_container.py)を挙げます。このスクリプトは、Braket によって事前に構築されたイメージがアルゴリズムスクリプトを起動し、適切な環境変数を設定するために使用します。コンテナエントリポイントスクリプト自体は Python で記述される**必要があります**が、Python 以外のスクリプトも起動できます。当該の構築済みの例では Python アルゴリズムスクリプトが [Python サブプロセス](https://github.com/amazon-braket/amazon-braket-containers/blob/main/src/braket_container.py#L274)または[まったく新しいプロセス](https://github.com/amazon-braket/amazon-braket-containers/blob/main/src/braket_container.py#L257)として起動されていることが分かります。このロジックを変更することで、Python 以外のアルゴリズムスクリプトをエントリポイントスクリプトが起動できるようにすることができます。例えば、末尾に付いているファイル拡張子に応じて Rust プロセスを起動するように [https://github.com/amazon-braket/amazon-braket-containers/blob/main/src/braket_container.py#L139](https://github.com/amazon-braket/amazon-braket-containers/blob/main/src/braket_container.py#L139) 関数を変更できます。

まったく新しい `braket_container.py` を記述することもできます。その Python スクリプトでは、入力データ、ソースアーカイブ、その他の必要なファイルを Amazon S3 からコンテナにコピーし、適切な環境変数を定義する必要があります。

## `Dockerfile` を使用して必要なソフトウェアとコンテナスクリプトをインストールする
<a name="install-docketfile"></a>

**注記**  
構築済みの Braket イメージを Docker ベースイメージとして使用する場合、コンテナスクリプトは既に存在しています。

直前のステップで、変更したコンテナスクリプトを作成した場合は、それをコンテナにコピーし、**かつ**環境変数 `SAGEMAKER_PROGRAM` を、`braket_container.py` か、新しいコンテナエントリポイントスクリプトに付けた名前に設定します。

以下は、GPU アクセラレーションジョブインスタンスで Julia を使用できるようにする `Dockerfile` の例です。

```
FROM nvidia/cuda:12.2.0-devel-ubuntu22.04

    
 ARG DEBIAN_FRONTEND=noninteractive
 ARG JULIA_RELEASE=1.8
 ARG JULIA_VERSION=1.8.3


 ARG PYTHON=python3.11 
 ARG PYTHON_PIP=python3-pip
 ARG PIP=pip


 ARG JULIA_URL = https://julialang-s3.julialang.org/bin/linux/x64/${JULIA_RELEASE}/
 ARG TAR_NAME = julia-${JULIA_VERSION}-linux-x86_64.tar.gz


 ARG PYTHON_PKGS = # list your Python packages and versions here


 RUN curl -s -L ${JULIA_URL}/${TAR_NAME} | tar -C /usr/local -x -z --strip-components=1 -f -


 RUN apt-get update \

    && apt-get install -y --no-install-recommends \

    build-essential \

    tzdata \

    openssh-client \

    openssh-server \

    ca-certificates \

    curl \

    git \

    libtemplate-perl \

    libssl1.1 \

    openssl \

    unzip \ 

    wget \

    zlib1g-dev \

    ${PYTHON_PIP} \

    ${PYTHON}-dev \




 RUN ${PIP} install --no-cache --upgrade ${PYTHON_PKGS}


 RUN ${PIP} install --no-cache --upgrade sagemaker-training==4.1.3


 # Add EFA and SMDDP to LD library path
 ENV LD_LIBRARY_PATH="/opt/conda/lib/python${PYTHON_SHORT_VERSION}/site-packages/smdistributed/dataparallel/lib:$LD_LIBRARY_PATH"
 ENV LD_LIBRARY_PATH=/opt/amazon/efa/lib/:$LD_LIBRARY_PATH


 # Julia specific installation instructions
 COPY Project.toml /usr/local/share/julia/environments/v${JULIA_RELEASE}/
 RUN JULIA_DEPOT_PATH=/usr/local/share/julia \

    julia -e 'using Pkg; Pkg.instantiate(); Pkg.API.precompile()'
 # generate the device runtime library for all known and supported devices
 RUN JULIA_DEPOT_PATH=/usr/local/share/julia \

    julia -e 'using CUDA; CUDA.precompile_runtime()'


 # Open source compliance scripts
 RUN HOME_DIR=/root \

 && curl -o ${HOME_DIR}/oss_compliance.zip https://aws-dlinfra-utilities.s3.amazonaws.com/oss_compliance.zip \

 && unzip ${HOME_DIR}/oss_compliance.zip -d ${HOME_DIR}/ \

 && cp ${HOME_DIR}/oss_compliance/test/testOSSCompliance /usr/local/bin/testOSSCompliance \

 && chmod +x /usr/local/bin/testOSSCompliance \

 && chmod +x ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh \

 && ${HOME_DIR}/oss_compliance/generate_oss_compliance.sh ${HOME_DIR} ${PYTHON} \

 && rm -rf ${HOME_DIR}/oss_compliance*


 # Copying the container entry point script
 COPY braket_container.py /opt/ml/code/braket_container.py
 ENV SAGEMAKER_PROGRAM braket_container.py
```

この例では、 は が提供するスクリプトをダウンロードして実行 AWS し、関連するすべてのオープンソースライセンスへの準拠を確保します。この遵守は例えば、MIT license が適用されるインストール済みコードに対し、適切な帰属表現を行う、といった方法によって行われます。

プライベートな GitHub または GitLab のリポジトリでホストされているコードなど、公開されていないコードを含める必要がある場合は、そういったコードにアクセスするための SSH キーを Docker イメージに埋め込ま**ないでください**。代わりに、構築時に Docker Compose を使用することで、構築のベースとするホストマシン上の SSH へのアクセスを Docker に許可します。詳細については、ガイド「[Securely using SSH keys in Docker to access private Github repositories](https://www.fastruby.io/blog/docker/docker-ssh-keys.html)」を参照してください。

**Docker イメージを構築し、アップロードする**

`Dockerfile` を適切に定義できたため、[プライベート Amazon ECR リポジトリ (がまだ存在しない場合に、それ) を作成する](https://docs.aws.amazon.com/AmazonECR/latest/userguide/repository-create.html)手順を実行する準備が整いました。また、コンテナイメージの構築、タグ付け、リポジトリへのアップロードも行うことができます。

イメージを構築、タグ付け、プッシュする準備ができたとします。`docker build` のオプションの完全な説明といくつかの例については、「[Docker build documentation](https://docs.docker.com/reference/cli/docker/buildx/build/)」を参照してください。

上記のサンプルファイルの場合は、以下を実行できます。

```
aws ecr get-login-password --region ${your_region} | docker login --username AWS --password-stdin ${aws_account_id}.dkr.ecr.${your_region}.amazonaws.com
 docker build -t braket-julia .
 docker tag braket-julia:latest ${aws_account_id}.dkr.ecr.${your_region}.amazonaws.com/braket-julia:latest
 docker push ${aws_account_id}.dkr.ecr.${your_region}.amazonaws.com/braket-julia:latest
```

**適切な Amazon ECR アクセス許可を割り当てる**

Braket Hybrid Jobs Docker イメージは、プライベートな Amazon ECR リポジトリでホストされている必要があります。デフォルトでは、プライベート Amazon ECR リポジトリは、Braket Hybrid Jobs IAM role への読み取りアクセスや、共同作業者や学生などイメージの使用を希望する他のユーザーへの読み取りアクセスを提供**しません**。適切なアクセス許可を付与する[リポジトリポリシーを設定する](https://docs.aws.amazon.com/AmazonECR/latest/userguide/set-repository-policy.html)必要があります。一般に、イメージにアクセスしてもらう必要がある特定のユーザーおよび IAM ロールにのみアクセス許可を付与し、当該の image URI を持つ任意のユーザーにイメージのプルを許可しないでください。

# 独自のコンテナでの Braket ハイブリッドジョブの実行
<a name="running-hybrid-jobs-in-own-container"></a>

独自のコンテナでハイブリッドジョブを作成するには、指定された `image_uri` 引数を使用して、`AwsQuantumJob.create()` を呼び出します。QPU かオンデマンドシミュレーターを使用することも、Braket Hybrid Jobs で使用できる古典的プロセッサでコードをローカルに実行することもできます。実際の QPU で実行する前に、SV1、DM1、TN1 などのシミュレーターでコードをテストすることをお勧めします。

古典的プロセッサでコードを実行するには、`InstanceConfig` を更新して、`instanceType` および使用する `instanceCount` を指定します。`instance_count` > 1 を指定する場合は、コードが複数のホストで実行できることを確認しておく必要があります。選択できるインスタンスの数の上限は 5 です。例えば、次のようになります。

```
job = AwsQuantumJob.create(
    source_module="source_dir",
    entry_point="source_dir.algorithm_script:start_here",
    image_uri="111122223333.dkr.ecr.us-west-2.amazonaws.com/my-byoc-container:latest",
    instance_config=InstanceConfig(instanceType="ml.g4dn.xlarge", instanceCount=3),
    device="local:braket/braket.local.qubit",
    # ...)
```

**注記**  
デバイス ARN を使用して、ハイブリッドジョブメタデータとして使用したシミュレーターを追跡します。「`device = "local:<provider>/<simulator_name>"`」の形式に従った値が許容されます。`<provider>` および `<simulator_name>` は英字、数字、`_`、`-`、および `.` のみで構成する必要があります。文字列サイズは 256 文字に制限されています。  
BYOC を使用する予定で、Braket SDK を使用しないで量子タスクを作成する場合は、環境変数 `AMZN_BRAKET_JOB_TOKEN` の値を`CreateQuantumTask` リクエストの`jobToken` パラメータに渡す必要があります。そうしないと、量子タスクは優先されず、通常のスタンドアロン量子タスクとして請求されます。

# ハイパーパラメータの使用方法
<a name="braket-jobs-hyperparameters"></a>

ハイブリッドジョブを作成するときに、学習率やステップサイズなど、アルゴリズムに必要なハイパーパラメータを定義できます。ハイパーパラメータ値は通常、アルゴリズムのさまざまな側面を制御するために使用され、多くの場合、アルゴリズムのパフォーマンスを最適化するために調整できます。Braket ハイブリッドジョブでハイパーパラメータを使用するには、ハイパーパラメータの名前と値をディクショナリとして明示的に指定する必要があります。最適な値のセットを検索するときにテストするハイパーパラメーター値を指定してください。ハイパーパラメータを使用するための最初のステップは、ハイパーパラメータをディクショナリとして設定して定義することです。このステップは、次のコードで確認できます。

```
from braket.devices import Devices

device_arn = Devices.Amazon.SV1

hyperparameters = {"shots": 1_000}
```

次に、上記のコードスニペットで定義されているハイパーパラメータを、選択したアルゴリズムに渡して使用されるようにします。次のコード例を実行するには、ハイパーパラメータファイルと同じパスに「src」という名前のディレクトリを作成します。「src」ディレクトリ内に、[0\$1Getting\$1started\$1papermill.ipynb](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/7_Running_notebooks_as_hybrid_jobs/src/0_Getting_started_papermill.ipynb)、[notebook\$1runner.py](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/7_Running_notebooks_as_hybrid_jobs/src/notebook_runner.py)、および [requirements.txt](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/7_Running_notebooks_as_hybrid_jobs/src/requirements.txt) コードファイルを追加します。

```
import time
from braket.aws import AwsQuantumJob

job = AwsQuantumJob.create(
    device=device_arn,
    source_module="src",
    entry_point="src.notebook_runner:run_notebook",
    input_data="src/0_Getting_started_papermill.ipynb",
    hyperparameters=hyperparameters,
    job_name=f"papermill-job-demo-{int(time.time())}",
)

# Print job to record the ARN
print(job)
```

ハイブリッドジョブスクリプト*内*からハイパーパラメータにアクセスするには、[notebook\$1runner.py](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/7_Running_notebooks_as_hybrid_jobs/src/notebook_runner.py) Python ファイル内の `load_jobs_hyperparams()` 関数を参照してください。ハイブリッドジョブスクリプトの*外部*からハイパーパラメータにアクセスするには、次のコードを実行します。

```
from braket.aws import AwsQuantumJob

# Get the job using the ARN
job_arn = "arn:aws:braket:us-east-1:111122223333:job/5eabb790-d3ff-47cc-98ed-b4025e9e296f"  # Replace with your job ARN
job = AwsQuantumJob(arn=job_arn)

# Access the hyperparameters
job_metadata = job.metadata()
hyperparameters = job_metadata.get("hyperParameters", {})
print(hyperparameters)
```

ハイパーパラメータの使用方法の詳細については、「[QAOA with Amazon Braket Hybrid Jobs and PennyLane](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/2_Using_PennyLane_with_Braket_Hybrid_Jobs/Using_PennyLane_with_Braket_Hybrid_Jobs.ipynb)」および「[Quantum machine learning in Amazon Braket Hybrid Jobs](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/1_Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs/Quantum_machine_learning_in_Amazon_Braket_Hybrid_Jobs.ipynb)」を参照してください。

# ハイブリッドジョブインスタンスの設定
<a name="braket-jobs-configure-job-instance-for-script"></a>

アルゴリズムによっては、要件が異なる場合があります。デフォルトでは、Amazon Braket はアルゴリズムスクリプトを`ml.m5.large` インスタンスで実行します。ただし、次のインポートおよび構成引数を使用してハイブリッドジョブを作成する場合は、このインスタンスタイプをカスタマイズできます。

```
from braket.jobs.config import InstanceConfig

job = AwsQuantumJob.create(
    ...
    instance_config=InstanceConfig(instanceType="ml.g4dn.xlarge"), # Use NVIDIA T4 instance with 4 GPUs.
    ...
    ),
```

埋め込みシミュレーションを実行する場合に、デバイス設定でローカルデバイスが指定されているときは、`instanceCount` を指定して 1 より大きな値に設定することで、`InstanceConfig` で複数のインスタンスを追加でリクエストできます。上限は 5 です。例えば、次のように 3 つのインスタンスを選択できます。

```
from braket.jobs.config import InstanceConfig
job = AwsQuantumJob.create(
    ...
    instance_config=InstanceConfig(instanceType="ml.g4dn.xlarge", instanceCount=3), # Use 3 NVIDIA T4 instances
    ...
    ),
```

複数のインスタンスを使用する場合は、データ並列機能を使用してハイブリッドジョブを分散することを検討してください。これを表示する方法の詳細については、ノートブックの例である「[Parallelize training for QML](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/5_Parallelize_training_for_QML/Parallelize_training_for_QML.ipynb)」を参照してください。

次の 3 つの表は、スタンダードインスタンス、ハイパフォーマンスインスタンス、GPU 高速化インスタンスのぞれぞれで使用可能なインスタンスタイプと仕様の一覧です。

**注記**  
Hybrid Jobs のデフォルトの古典コンピューティングインスタンスクォータを表示するには、「[Amazon Braket Quotas](braket-quotas.md)」ページを参照してください。


| スタンダードインスタンス | vCPU | メモリ (GiB) | 
| --- | --- | --- | 
|  ml.m5.large (デフォルト)  |  4  |  16  | 
|  ml.m5.xlarge  |  4  |  16  | 
|  ml.m5.2xlarge  |  8  |  32  | 
|  ml.m5.4xlarge  |  16  |  64  | 
|  ml.m5.12xlarge  |  48  |  192  | 
|  ml.m5.24xlarge  |  96  |  384  | 


| ハイパフォーマンスインスタンス | vCPU | メモリ (GiB) | 
| --- | --- | --- | 
|  ml.c5.xlarge  |  4  |  8  | 
|  ml.c5.2xlarge  |  8  |  16  | 
|  ml.c5.4xlarge  |  16  |  32  | 
|  ml.c5.9xlarge  |  36  |  72  | 
|  ml.c5.18xlarge  |  72  |  144  | 
|  ml.c5n.xlarge  |  4  |  10.5  | 
|  ml.c5n.2xlarge  |  8  |  21  | 
|  ml.c5n.4xlarge  |  16  |  32  | 
|  ml.c5n.9xlarge  |  36  |  72  | 
|  ml.c5n.18xlarge  |  72  |  192  | 


| GPU 高速化インスタンス | GPUs | vCPU | メモリ (GiB) | GPU メモリ (GiB) | 
| --- | --- | --- | --- | --- | 
|  ml.p4d.24xlarge  |  8  |  96  |  1152  |  320  | 
|  ml.g4dn.xlarge  |  1  |  4  |  16  |  16  | 
|  ml.g4dn.2xlarge  |  1  |  8  |  32  |  16  | 
|  ml.g4dn.4xlarge  |  1  |  16  |  64  |  16  | 
|  ml.g4dn.8xlarge  |  1  |  32  |  128  |  16  | 
|  ml.g4dn.12xlarge  |  4  |  48  |  192  |  64  | 
|  ml.g4dn.16xlarge  |  1  |  64  |  256  |  16  | 

各インスタンスは、30 GB のデータストレージ (SSD) のデフォルト設定を使用します。ただし、ストレージは、`instanceType` を設定するのと同じ方法で調整できます。次の例では、ストレージの合計を 50 GB に増やす方法を示します。

```
from braket.jobs.config import InstanceConfig

job = AwsQuantumJob.create(
    ...
    instance_config=InstanceConfig(
        instanceType="ml.g4dn.xlarge",
        volumeSizeInGb=50,
    ),
    ...
    ),
```

## `AwsSession` でのデフォルトのバケットの設定
<a name="braket-jobs-configure-default-bucket"></a>

独自の`AwsSession` インスタンスを使用すると、カスタマイズしたデフォルトの Amazon S3 バケットの場所を指定する機能など、柔軟性が向上します。デフォルトでは、Amazon S3 バケットの場所 `"amazon-braket-{id}-{region}"` が `AwsSession` に事前設定されています。ただし、`AwsSession` の作成時に、デフォルトの Amazon S3 バケットの場所を上書きしておくこともできます。ユーザーはオプションで `AwsSession` オブジェクトを `AwsQuantumJob.create()` メソッドに渡すことができます。それには、次のコード例に示すように `aws_session` パラメータを指定します。

```
aws_session = AwsSession(default_bucket="amazon-braket-s3-demo-bucket")

# Then you can use that AwsSession when creating a hybrid job
job = AwsQuantumJob.create(
    ...
    aws_session=aws_session
)
```

# パラメトリックコンパイルを使用したハイブリッドジョブの高速化
<a name="braket-jobs-parametric-compilation"></a>

 Amazon Braket は、特定の QPU でのパラメトリックコンパイルをサポートしています。このサポートにより、ハイブリッドアルゴリズムの各イテレーションをコンパイルするのではなく、回路を 1 回コンパイルするだけで済むようになるため、計算コストの高いコンパイルステップにかかるオーバーヘッドを削減できます。これにより、各ステップで回路を再コンパイルする必要がなくなるため、ハイブリッドジョブの実行時間が大幅に短縮されます。パラメータ化された回路を Braket ハイブリッドジョブとして、サポートされている QPU のいずれかに送信するだけでよいのです。長時間実行されるハイブリッドジョブの場合、Braket は、回路をコンパイルするときに、ハードウェアプロバイダーからの更新されたキャリブレーションデータを自動的に使用して、最高品質の結果を実現します。

パラメトリック回路を作成するには、まずパラメータをアルゴリズムスクリプトの入力として指定する必要があります。次の例では、小さなパラメトリック回路を使用し、各イテレーション間の古典的な処理をすべて無視しています。標準的なワークロードなら、多数の回路をバッチで送信し、各イテレーションでパラメータを更新するなどの古典的な処理を実行するところです。

```
import os

from braket.aws import AwsDevice
from braket.circuits import Circuit, FreeParameter

def start_here():

    print("Test job started.")

    # Use the device declared in the job script
    device = AwsDevice(os.environ["AMZN_BRAKET_DEVICE_ARN"])

    circuit = Circuit().rx(0, FreeParameter("theta"))
    parameter_list = [0.1, 0.2, 0.3]
    
    for parameter in parameter_list:
        result = device.run(circuit, shots=1000, inputs={"theta": parameter})

    print("Test job completed.")
```

次のジョブスクリプトを使用して、ハイブリッドジョブとして実行するアルゴリズムスクリプトを送信できます。パラメトリックコンパイルをサポートする QPU でハイブリッドジョブを実行する場合、回路は最初の実行時にのみコンパイルされます。後続の実行では、コンパイルされた回路が再利用されるため、コード行を追加しなくてもハイブリッドジョブの実行時間が短縮されます。

```
from braket.aws import AwsQuantumJob

job = AwsQuantumJob.create(
    device=device_arn,
    source_module="algorithm_script.py",
)
```

**注記**  
パラメトリックコンパイルは、Rigetti Computing 製のあらゆる超伝導ゲートベース QPU でサポートされています。ただし、パルスレベルプログラムは例外です。

# PennyLane と Amazon Braket の併用
<a name="hybrid"></a>

ハイブリッドアルゴリズムは、古典命令と量子命令の両方を含むアルゴリズムです。古典命令は、古典的なハードウェア (EC2 インスタンスまたはノートパソコン) で実行され、量子命令はシミュレーターまたは量子コンピュータ上で実行されます。Hybrid Jobs の機能を使用してハイブリッドアルゴリズムを実行することをお勧めします。詳細については、「[Amazon Braket ジョブを使用する時期](braket-jobs.md#braket-jobs-use)」を参照してください。

Amazon Braket では、**Amazon Braket PennyLane プラグイン**または **Amazon Braket Python SDK** およびサンプルノートブックリポジトリの助けを借りてハイブリッド量子アルゴリズムを設定および実行できます。SDK に基づく Amazon Braket のサンプルノートブックを使用すると、PennyLane プラグインを使用せずに特定のハイブリッドアルゴリズムを設定および実行できます。しかし、PennyLane を使用した方が、リッチな体験が提供されるため、PennyLane の使用をお勧めします。

 **ハイブリッド量子アルゴリズムについて** 

現代の量子コンピューティングデバイスは、一般的にノイズを生成し、このためエラーも生成するため、ハイブリッド量子アルゴリズムは今日の業界にとって重要です。コンピューティングに追加されるすべての量子ゲートにより、ノイズが増える可能性が高くなります。したがって、長時間実行されるアルゴリズムはノイズによって圧倒され、計算エラーが発生する可能性があります。

ショア [(Quantum Phase Estimation [量子位相推定] の例)](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/advanced_circuits_algorithms/Quantum_Phase_Estimation) またはグローバー[(Grover の例)](https://github.com/aws/amazon-braket-examples/tree/main/examples/advanced_circuits_algorithms/Grover) などの純粋な量子アルゴリズムには、数千または数百万ものオペレーションが必要です。このため、これらは既存の量子デバイスでは実行できない可能性があります。これらの量子デバイスは、一般に*ノイズの多い中間スケール量子*(NISQ) デバイスと呼ばれます。

ハイブリッド量子アルゴリズムでは、特に古典的なアルゴリズムにおける特定の計算を高速化するために、量子処理ユニット (QPU) は古典的 CPU のコプロセッサとして機能します。今日のデバイスの機能によって実現できる範囲において、回路の実行がはるかに短くなります。

**Topics**
+ [PennyLane と Amazon Braket](#pennylane-option)
+ [Amazon Braket のハイブリッドアルゴリズムのサンプルノートブック](#braket-hybrid-workflow)
+ [PennyLane シミュレーターが埋め込まれたハイブリッドアルゴリズム](#hybrid-alorithms-pennylane)
+ [Amazon Braket シミュレーターを使用した PennyLane による随伴勾配](#adjoint-gradient-pennylane)
+ [Hybrid Jobs と PennyLane を使用した QAOA アルゴリズムの実行](braket-jobs-run-qaoa-algorithm.md)
+ [PennyLane 埋め込みシミュレーターを使用したハイブリッドワークロードの実行](pennylane-embedded-simulators.md)

## PennyLane と Amazon Braket
<a name="pennylane-option"></a>

Amazon Braket は、[PennyLane](https://pennylane.ai) のサポートを提供し、*量子微分可能プログラミング*のコンセプトを中心に構築されたオープンソースのソフトウェアフレームワークです。このフレームワークは、量子化学、量子機械学習、最適化におけるコンピューティング問題の解を見つけるために、ニューラルネットワークをトレーニングするのと同じ方法で量子回路をトレーニングするのに利用可能です。

PennyLane ライブラリは、PyTorch や TensorFlow など、使い慣れた機械学習ツールへのインターフェースを提供し、量子回路のトレーニングを直感的に簡単に行えます。
+  **PennyLane Library** - PennyLane は Amazon Braket ノートブックに事前にインストールされています。PennyLane から Amazon Braket デバイスにアクセスするには、ノートブックを開き、次のコマンドを使用して PennyLane ライブラリをインポートします。

```
import pennylane as qml
```

チュートリアルノートブックで、すぐに開始できます。または、お好みの IDE から Amazon Braket で PennyLane を使用することもできます。
+  **Amazon Braket PennyLane プラグイン** — 独自の IDE を使用するには、Amazon Braket PennyLane プラグインを手動でインストールできます。プラグインは PennyLane を [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) に接続するので、Amazon Braket デバイスで PennyLane 内の回路を実行できます。PennyLane プラグインをインストールするには、次のコマンドを使用します。

```
pip install amazon-braket-pennylane-plugin
```

以下の例は、PennyLane で Amazon Braket デバイスへのアクセスを設定する方法を示しています。

```
# to use SV1
import pennylane as qml
sv1 = qml.device("braket.aws.qubit", device_arn="arn:aws:braket:::device/quantum-simulator/amazon/sv1", wires=2)

# to run a circuit:
@qml.qnode(sv1)
def circuit(x):
    qml.RZ(x, wires=0)
    qml.CNOT(wires=[0,1])
    qml.RY(x, wires=1)
    return qml.expval(qml.PauliZ(1))

result = circuit(0.543)


#To use the local sim:
local = qml.device("braket.local.qubit", wires=2)
```

PennyLane のチュートリアルの例と詳細については、「[Amazon Braket examples](https://github.com/aws/amazon-braket-examples/tree/main/examples/pennylane)」リポジトリを参照してください。

Amazon Braket PennyLane プラグインを使用すると、1 行のコードで Amazon Braket QPU と PennyLane のシミュレーターデバイスを切り替えることができます。PennyLane プラグインは、それ自体とともに動作する 2 つの Amazon Braket 量子デバイスを提供しています。
+  `braket.aws.qubit`: Amazon Braket サービスの量子デバイス (QPU やシミュレーターを含む) を使用して実行するデバイス
+  `braket.local.qubit`: Amazon Braket SDK のローカルシミュレーターで実行するデバイス

Amazon Braket PennyLane プラグインはオープンソースです。インストールは [PennyLane Plugin](https://github.com/aws/amazon-braket-pennylane-plugin-python) GitHub リポジトリから行えます。

PennyLane の詳細については、[PennyLane ウェブサイト](https://pennylane.ai)のドキュメントを参照してください。

## Amazon Braket のハイブリッドアルゴリズムのサンプルノートブック
<a name="braket-hybrid-workflow"></a>

Amazon Braket では、ハイブリッドアルゴリズムの実行に PennyLane プラグインに依存しないさまざまなサンプルノートブックを提供しています。量子近似最適化アルゴリズム (QAOA) や変分量子固有値ソルバー (VQE) などの[変分法](https://github.com/aws/amazon-braket-examples/tree/main/examples/hybrid_quantum_algorithms)を説明する *Amazon Braket ハイブリッドサンプルノートブック*のいずれからでも開始できます。

Amazon Braket のサンプルノートブックは、[Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python) に依存しています。SDK は Amazon Braket を通じて量子コンピューティングハードウェアデバイスを操作するためのフレームワークを提供します。これは、ハイブリッドワークフローの量子部分を支援するために設計されたオープンソースライブラリです。

Amazon Braket は、「[example](https://github.com/aws/amazon-braket-examples) のノートブックで詳しく調べることができます。

## PennyLane シミュレーターが埋め込まれたハイブリッドアルゴリズム
<a name="hybrid-alorithms-pennylane"></a>

Amazon Braket Hybrid Jobs に、[PennyLane](https://github.com/PennyLaneAI/pennylane-lightning) のハイパフォーマンスの CPU ベースおよび GPU ベースの埋め込みシミュレーターが追加されました。この埋め込みシミュレーターファミリーはハイブリッドジョブコンテナに直接埋め込むことができ、高速状態ベクトルの `lightning.qubit` シミュレーターと、NVIDIA の [cuQuantum ライブラリ](https://developer.nvidia.com/cuquantum-sdk)を使用して高速化された `lightning.gpu` シミュレーターなどが含まれています。これらの埋め込みシミュレーターは、[随伴区別](https://docs.pennylane.ai/en/stable/introduction/interfaces.html#simulation-based-differentiation)方法などの高度な方法の利点を享受できる量子機械学習などのバリエーションアルゴリズムに最適です。これらの埋め込みシミュレーターは、1 つまたは複数の CPU または GPU インスタンスで実行できます。

Hybrid Jobs により、古典的なコプロセッサと QPU の組み合わせや SV1 などの Amazon Braket オンデマンドシミュレーターを使用したり、PennyLane の埋め込みシミュレーターを直接使用したりすることで、変分アルゴリズムコードを実行できるようになりました。

埋め込みシミュレーターは Hybrid Jobs コンテナでは既に利用可能になっています。利用するには、メインの Python 関数を `@hybrid_job` デコレータでデコレートしてください。PennyLane `lightning.gpu` シミュレーターを使用するには、次のコードスニペットに示すように `InstanceConfig` 内に GPU インスタンスを指定する必要があります。

```
import pennylane as qml
from braket.jobs import hybrid_job
from braket.jobs.config import InstanceConfig


@hybrid_job(device="local:pennylane/lightning.gpu", instance_config=InstanceConfig(instanceType="ml.g4dn.xlarge"))
def function(wires):
    dev = qml.device("lightning.gpu", wires=wires)
    ...
```

ハイブリッドジョブで PennyLane 埋め込みシミュレーターの使用を開始するには、「[example ](https://github.com/aws/amazon-braket-examples/blob/main/examples/hybrid_jobs/4_Embedded_simulators_in_Braket_Hybrid_Jobs/Embedded_simulators_in_Braket_Hybrid_Jobs.ipynb)」のノートブックを参照してください。

## Amazon Braket シミュレーターを使用した PennyLane による随伴勾配
<a name="adjoint-gradient-pennylane"></a>

Amazon Braket 用 PennyLane プラグインを使用すると、ローカル状態ベクトルシミュレーターまたは SV1 で勾配計算を実行する際に、随伴微分法を使用できます。

 **注:** 随伴微分法を使用するには、`qnode` 内に、`diff_method='adjoint'`**ではなく** `diff_method='device'` を指定する必要があります。次の例を参照してください。

```
device_arn = "arn:aws:braket:::device/quantum-simulator/amazon/sv1"
dev = qml.device("braket.aws.qubit", wires=wires, shots=0, device_arn=device_arn)
                
@qml.qnode(dev, diff_method="device")
def cost_function(params):
    circuit(params)
    return qml.expval(cost_h)

gradient = qml.grad(circuit)
initial_gradient = gradient(params0)
```

**注記**  
現行では、PennyLane は QAOA ハミルトニアンのグループ化インデックスを計算し、それらのインデックスを使用してハミルトニアンを複数の期待値に分割します。PennyLane から QAOA を実行するときに、SV1 の随伴微分機能を使用する場合は、次のようにグループ化インデックスを削除してコストハミルトニアンを新規に構築する必要があります: `cost_h, mixer_h = qml.qaoa.max_clique(g, constrained=False) cost_h = qml.Hamiltonian(cost_h.coeffs, cost_h.ops)` 

# Hybrid Jobs と PennyLane を使用した QAOA アルゴリズムの実行
<a name="braket-jobs-run-qaoa-algorithm"></a>

このセクションでは、学習内容を活用し、パラメトリックコンパイルを指定して PennyLane を使用し、実際のハイブリッドプログラムを作成します。アルゴリズムスクリプトを使用して、量子近似最適化アルゴリズム (QAOA) 問題に対処します。このプログラムでは、古典的な最大カット最適化問題に対応するコスト関数を作成し、パラメータ化された量子回路を指定し、勾配降下法を使用してコスト関数が最小化されるようにパラメータを最適化します。この例では、単純化のためにアルゴリズムスクリプトで問題グラフを生成しますが、より一般的なユースケースでは、入力データ構成の専用チャネルを通じて問題の仕様を提供するのがベストプラクティスです。フラグ `parametrize_differentiable` のデフォルトは `True` であるため、サポートされている QPU でのパラメトリックコンパイルによる実行時間短縮のメリットが自動的に得られます。

```
import os
import json
import time

from braket.jobs import save_job_result
from braket.jobs.metrics import log_metric

import networkx as nx
import pennylane as qml
from pennylane import numpy as np
from matplotlib import pyplot as plt

def init_pl_device(device_arn, num_nodes, shots, max_parallel):
    return qml.device(
        "braket.aws.qubit",
        device_arn=device_arn,
        wires=num_nodes,
        shots=shots,
        # Set s3_destination_folder=None to output task results to a default folder
        s3_destination_folder=None,
        parallel=True,
        max_parallel=max_parallel,
        parametrize_differentiable=True, # This flag is True by default.
    )

def start_here():
    input_dir = os.environ["AMZN_BRAKET_INPUT_DIR"]
    output_dir = os.environ["AMZN_BRAKET_JOB_RESULTS_DIR"]
    job_name = os.environ["AMZN_BRAKET_JOB_NAME"]
    checkpoint_dir = os.environ["AMZN_BRAKET_CHECKPOINT_DIR"]
    hp_file = os.environ["AMZN_BRAKET_HP_FILE"]
    device_arn = os.environ["AMZN_BRAKET_DEVICE_ARN"]

    # Read the hyperparameters
    with open(hp_file, "r") as f:
        hyperparams = json.load(f)

    p = int(hyperparams["p"])
    seed = int(hyperparams["seed"])
    max_parallel = int(hyperparams["max_parallel"])
    num_iterations = int(hyperparams["num_iterations"])
    stepsize = float(hyperparams["stepsize"])
    shots = int(hyperparams["shots"])

    # Generate random graph
    num_nodes = 6
    num_edges = 8
    graph_seed = 1967
    g = nx.gnm_random_graph(num_nodes, num_edges, seed=graph_seed)

    # Output figure to file
    positions = nx.spring_layout(g, seed=seed)
    nx.draw(g, with_labels=True, pos=positions, node_size=600)
    plt.savefig(f"{output_dir}/graph.png")

    # Set up the QAOA problem
    cost_h, mixer_h = qml.qaoa.maxcut(g)

    def qaoa_layer(gamma, alpha):
        qml.qaoa.cost_layer(gamma, cost_h)
        qml.qaoa.mixer_layer(alpha, mixer_h)

    def circuit(params, **kwargs):
        for i in range(num_nodes):
            qml.Hadamard(wires=i)
        qml.layer(qaoa_layer, p, params[0], params[1])

    dev = init_pl_device(device_arn, num_nodes, shots, max_parallel)

    np.random.seed(seed)
    cost_function = qml.ExpvalCost(circuit, cost_h, dev, optimize=True)
    params = 0.01 * np.random.uniform(size=[2, p])

    optimizer = qml.GradientDescentOptimizer(stepsize=stepsize)
    print("Optimization start")

    for iteration in range(num_iterations):
        t0 = time.time()

        # Evaluates the cost, then does a gradient step to new params
        params, cost_before = optimizer.step_and_cost(cost_function, params)
        # Convert cost_before to a float so it's easier to handle
        cost_before = float(cost_before)

        t1 = time.time()

        if iteration == 0:
            print("Initial cost:", cost_before)
        else:
            print(f"Cost at step {iteration}:", cost_before)

        # Log the current loss as a metric
        log_metric(
            metric_name="Cost",
            value=cost_before,
            iteration_number=iteration,
        )

        print(f"Completed iteration {iteration + 1}")
        print(f"Time to complete iteration: {t1 - t0} seconds")

    final_cost = float(cost_function(params))
    log_metric(
        metric_name="Cost",
        value=final_cost,
        iteration_number=num_iterations,
    )

    # We're done with the hybrid job, so save the result.
    # This will be returned in job.result()
    save_job_result({"params": params.numpy().tolist(), "cost": final_cost})
```

**注記**  
パラメトリックコンパイルは、Rigetti Computing 製のあらゆる超伝導ゲートベース QPU でサポートされています。ただし、パルスレベルプログラムは例外です。

# PennyLane 埋め込みシミュレーターを使用したハイブリッドワークロードの実行
<a name="pennylane-embedded-simulators"></a>

Amazon Braket Hybrid Jobs で PennyLane の埋め込みシミュレーターを使用してハイブリッドワークロードを実行する方法について見ていきましょう。Pennylane の GPU ベースの埋め込みシミュレーター `lightning.gpu` は、[Nvidia cuQuantum ライブラリ](https://developer.nvidia.com/cuquantum-sdk)を使用して回路のシミュレーションを高速化します。埋め込み GPU シミュレーターは、ユーザーがすぐに使用できるすべての Braket [ジョブコンテナ](https://github.com/amazon-braket/amazon-braket-containers)に事前設定されています。このページでは、`lightning.gpu` を使用してハイブリッドワークロードを高速化する方法を示します。

## QAOA ワークロードに `lightning.gpu` を使用する
<a name="lightning-gpu-qaoa"></a>

[こちらのノートブック](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/hybrid_jobs/2_Using_PennyLane_with_Braket_Hybrid_Jobs)にある量子近似最適化アルゴリズム (QAOA) の例について考えてみましょう。埋め込みシミュレーターを選択するには、引数 `device` を `"local:<provider>/<simulator_name>"` という形式の文字列として指定します。例えば、`lightning.gpu` の場合なら `"local:pennylane/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 ベース) を比較します。各シミュレーターにカスタムゲート分解を提供して、さまざまな勾配を計算させます。

これで、ハイブリッドジョブ起動スクリプトを作成する準備ができました。`ml.m5.2xlarge` と `ml.g4dn.xlarge` の 2 つのインスタンスタイプを使用して QAOA アルゴリズムを実行します。`ml.m5.2xlarge` インスタンスタイプは、開発者用の標準的なラップトップに相当します。`ml.g4dn.xlarge` は、16GB のメモリを持つ単一の NVIDIA T4 GPU を持つ高速コンピューティングインスタンスです。

GPU を実行するには、まず互換性のあるイメージと正しいインスタンス (デフォルトで`ml.m5.2xlarge`はインスタンス) を指定する必要があります。

```
from braket.aws import AwsSession
from braket.jobs.image_uris import Framework, retrieve_image

image_uri = retrieve_image(Framework.PL_PYTORCH, AwsSession().region)
instance_config = InstanceConfig(instanceType="ml.g4dn.xlarge")
```

次に、これらをハイブリッドジョブデコレータに入力し、システム引数とハイブリッドジョブ引数の両方で更新されたデバイスパラメータを入力する必要があります。

```
@hybrid_job(
        device="local:pennylane/lightning.gpu",
        input_data=input_file_path,
        image_uri=image_uri,
        instance_config=instance_config)
def run_qaoa_hybrid_job_gpu(p=1, steps=10):
    params = np.random.rand(2, p)

    braket_task_tracker = Tracker()

    graph = nx.read_adjlist(input_file_path, nodetype=int)
    wires = list(graph.nodes)
    cost_h, _mixer_h = qaoa.maxcut(graph)

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

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

`m5.2xlarge` インスタンスの平均反復時間は約 73 秒で、`ml.g4dn.xlarge`インスタンスの平均反復時間は約 0.6 秒です。この 21 量子ビットのワークフローでは、GPU インスタンスによって 100 倍高速になります。Amazon Braket Hybrid Jobs の[料金ページ](https://aws.amazon.com/braket/pricing/)を見ると、`m5.2xlarge`インスタンスの 1 分あたりのコストは 0.00768 USD で、`ml.g4dn.xlarge`インスタンスのコストは 0.01227 USD であることがわかります。この例では、GPU インスタンスで実行する方が高速で安価です。

## 量子機械学習とデータ並列処理
<a name="quantumML-data-parallelism"></a>

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

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

二項分類の例としてよく知られている UCI リポジトリの [ソナーデータセット](https://archive.ics.uci.edu/dataset/151/connectionist+bench+sonar+mines+vs+rocks)を使用するデータ並列処理については、以下の QML ワークロードを検討してください。ソナーデータセットには 208 個のデータポイントがあります。各データポイントには、対象物から反射したソナー信号から収集された 60 個の特徴量があります。各データポイントには、機雷の場合は「M」、岩の場合は「R」というラベルが付けられます。当社の QML モデルは、入力レイヤー、非表示レイヤーとしての量子回路、および出力レイヤーで構成されています。入力レイヤーと出力レイヤーは、PyTorch 内に実装されている古典ニューラルネットです。量子回路は、PennyLane の qml.qnn モジュールを使用して PyTorch ニューラルネットと統合されています。ワークロードの詳細については、「[example](https://github.com/aws/amazon-braket-examples)」のノートブックを参照してください。上記の QAOA の例と同様に、PennyLane の `lightning.gpu` などの埋め込み GPU ベースのシミュレーターを使用して GPU の能力を活用することで、埋め込み CPU ベースのシミュレーターよりもパフォーマンスを向上させることができます。

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

```
instance_config = InstanceConfig(instanceType='ml.g4dn.xlarge')

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` パッケージをインポートします。このパッケージが、ワークロードを複数の GPU と複数のインスタンスに分散するための力仕事のほとんどを行います。このパッケージは Braket PyTorch コンテナと TensorFlow コンテナに事前設定されています。`dist` モジュールは、トレーニング (`world_size`) の GPU の合計数と GPU コアの `rank` と `local_rank` をアルゴリズムスクリプトに通知します。`rank` はすべてのインスタンスにおける GPU の絶対インデックスで、`local_rank` は特定のインスタンスにおける GPU のインデックスです。例えば、それぞれに 8 つの GPU が割り当てられた 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_size` と `rank` に従って `DistributedSampler` を定義し、それをデータローダーに渡します。次の例のサンプラー (sampler) は、データセットの同じスライスにアクセスする GPU を避けます。

```
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 が保存および出力コマンドを実行すると、ログは繰り返しの情報でいっぱいになり、結果は互いに上書きされます。これを回避するには、`rank` が 0 の 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.g4dn.12xlarge` インスタンスタイプをサポートしています。Hybrid Jobs で `InstanceConfig` 引数を使用してインスタンスタイプを設定します。SageMaker 分散データ並列ライブラリがデータ並列処理が有効になっていることを知るには、2 つのハイパーパラメータを追加する必要があります (`"sagemaker_distributed_dataparallel_enabled"` を `"true"` に設定し、`"sagemaker_instance_type"` を使用予定のインスタンスタイプに設定)。これら 2 つのハイパーパラメータは `smdistributed` パッケージで使用されます。これらのハイパーパラメータは、アルゴリズムスクリプトで明示的に使用する必要はありません。Amazon Braket SDK のアルゴリズムスクリプトには、便利なキーワード引数 `distribution` が備わっているためです。ハイブリッドジョブの作成で `distribution="data_parallel"` を使用することで、これら 2 つのハイパーパラメータが Amazon Braket SDK により自動的に挿入されるのです。Amazon Braket API を使用する場合は、これら 2 つのハイパーパラメータをユーザーが指定する必要があります。

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

```
instance_config = InstanceConfig(instanceType='ml.g4dn.12xlarge',
                                 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 が同じデータスライスを繰り返し処理したりすることがあります。後者は非効率です。

正しく使用すると、複数のインスタンスを使用すると、時間とコストの両方が大幅に削減される可能性があります。[ 詳細については、ノートブックの例を参照してください](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/5_Parallelize_training_for_QML/Parallelize_training_for_QML.ipynb)。

# CUDA-Q と Amazon Braket の併用方法
<a name="braket-using-cuda-q"></a>

NVIDIA's CUDA-Q は、CPU、GPU、量子処理ユニット (QPU) を組み合わせたハイブリッド量子アルゴリズムをプログラミングするために設計されたソフトウェアライブラリです。これは、開発者が古典命令と量子命令の両方を 1 つのプログラム内で表現できる統合されたプログラミングモデルを提供しているため、ワークフローを効率化できます。CUDA-Q は、埋め込みの CPU および GPU シミュレーターを使用することで、量子プログラムについてシミュレーションの高速化と実行時間の短縮を実現します。CUDA-Q は、ネイティブの Braket ノートブックインスタンス (NBI) と Amazon Braket Hybrid Jobs でご利用いただけます。

**Topics**
+ [NBI の CUDA-Q](#braket-cuda-q-nbis)
+ [Hybrid Jobs での CUDA-Q](#braket-cuda-q-hybrid-jobs)

## NBI の CUDA-Q
<a name="braket-cuda-q-nbis"></a>

CUDA-Q は、デフォルトで Braket NBI 環境にインストールされています。CUDA-Q のサンプルノートブックを開くには、Jupyter ランチャーページにアクセスし、[CUDA-Q と Braket タイル] を選択します。これにより、メインウィンドウでサンプルノートブック `0_Getting_started_with_CUDA-Q.ipynb` が開きます。その他の CUDA-Q のサンプルについては、左側のパネルにある `nvidia_cuda_q/` ディレクトリを参照してください。

また、CUDA-Q のバージョンや、NBI 内にインストールされているその他のサードパーティーパッケージを確認することもできます。例えば、環境にインストールされている CUDA-Q、Qiskit、PennyLane、および Braket パッケージのバージョンを確認するには、ノートブックのコードセルで次のコマンドを実行します。

```
%pip freeze | grep -i -e cudaq -e qiskit -e pennylane -e braket
```

## Hybrid Jobs での CUDA-Q
<a name="braket-cuda-q-hybrid-jobs"></a>

[Amazon Braket Hybrid Jobs](https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs.html) で CUDA-Q を使用することで、オンデマンドの柔軟なコンピューティング環境が提供されます。計算インスタンスはワークロードの期間中のみ実行されるので、使用した分に対してしか料金が発生しないことが保証されます。また、Amazon Braket Hybrid Jobs はスケーラブルなエクスペリエンスも提供します。ユーザーは、プロトタイプ作成とテストのために小さなインスタンスから始めておいて、後で、完全な実験を行うために、より大きなワークロードを処理できる大きなインスタンスにスケールアップすることもできます。

Amazon Braket Hybrid Jobs は、CUDA-Q の潜在能力を最大限に引き出すために不可欠な GPU をサポートしています。GPU は、CPU ベースのシミュレーターと比較して、量子プログラムのシミュレーションを大幅に高速化します。量子ビット数の大きな回路を使用する場合は特にそうなります。Amazon Braket Hybrid Jobs で CUDA-Q を使用すると、並列化が簡単になります。Hybrid Jobs が、回路のサンプリングとオブザーバブルの評価を複数の計算ノードに簡単に分散できるようにしたためです。この CUDA-Q ワークロードのシームレスな並列化により、ユーザーは大規模な実験の場合に、インフラストラクチャを構築せずにワークロードの開発に専念することができます。

開発を始めるには、Braket が提供する CUDA-Q ハイブリッドジョブコンテナを使用するための、「Amazon Braket examples」Github 内の「[CUDA-Q starter example](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/nvidia_cuda_q/0_Getting_started_with_CUDA-Q.ipynb)」を参照してください。

次のコードスニペットは、Amazon Braket Hybrid Jobs で CUDA-Q プログラムを実行する `hello-world` サンプルです。

```
image_uri = retrieve_image(Framework.CUDAQ, AwsSession().region)

@hybrid_job(device='local:nvidia/qpp-cpu', image_uri=image_uri)
def hello_quantum():
    import cudaq

    # define the backend
    device=get_job_device_arn()
    cudaq.set_target(device.split('/')[-1])

    # define the Bell circuit
    kernel = cudaq.make_kernel()
    qubits = kernel.qalloc(2)
    kernel.h(qubits[0])
    kernel.cx(qubits[0], qubits[1])

    # sample the Bell circuit
    result = cudaq.sample(kernel, shots_count=1000)
    measurement_probabilities = dict(result.items())
    
    return measurement_probabilities
```

上記の例では、CPU シミュレーターのベル回路をシミュレートしています。この例は、ラップトップまたは Braket Jupyter Notebook でローカルに実行します。このスクリプトを実行すると、`local=True` という設定により、ローカル環境でコンテナが開始されるため、テストおよびデバッグ用の CUDA-Q プログラムが実行されます。テストが完了したら、`local=True` フラグを削除することで、 AWSでジョブを実行できます。詳細については、「[Amazon Braket Hybrid Jobs の使用方法](braket-jobs.md)」を参照してください。

ワークロードに大きな量子ビット数、多数の回路、または多数の反復 (イテレーション) がある場合は、`instance_config` の設定値を指定することで、よりハイパフォーマンスの CPU コンピューティングリソースを使用できます。次のコードスニペットは、`hybrid_job` デコレータに `instance_config` の設定値を設定する方法を示しています。サポートされるインスタンスタイプの詳細については、「[ハイブリッドジョブインスタンスの設定](braket-jobs-configure-job-instance-for-script.md)」を参照してください。インスタンスタイプのリストについては「[Amazon EC2 インスタンスタイプ](https://aws.amazon.com/ec2/instance-types/)」を参照してください。

```
@hybrid_job(
    device="local:nvidia/qpp-cpu",
    image_uri=image_uri,
    instance_config=InstanceConfig(instanceType="ml.c5.2xlarge"),
)
def my_job_script():
    ...
```

より要求の厳しいワークロードの場合は、CUDA-Q GPU シミュレーターでワークロードを実行します。GPU シミュレーターを有効にするには、バックエンド名 `nvidia` を使用します。`nvidia` バックエンドは CUDA-Q GPU シミュレーターとして機能します。次に、NVIDIA GPU をサポートする Amazon EC2 インスタンスタイプを選択します。次のコードスニペットは、GPU が設定された `hybrid_job` デコレータを示しています。

```
@hybrid_job(
    device="local:nvidia/nvidia",
    image_uri=image_uri,
    instance_config=InstanceConfig(instanceType="ml.g4dn.xlarge"),
)
def my_job_script():
    ...
```

Amazon Braket Hybrid Jobs と NBI は、CUDA-Q を使用した並列 GPU シミュレーションをサポートしています。複数のオブザーバブルまたは複数の回路の評価を並列化することで、ワークロードのパフォーマンスを改善できます。複数のオブザーバブルを並列化するには、アルゴリズムスクリプトに以下の変更を加えます。

`nvidia` バックエンドの `mgpu` オプションを設定します。これは、オブザーバブルを並列化するために必要です。並列化は GPU 間の通信に MPI を使用するため、実行前に MPI を初期化しておき、実行後は MPI を確定する必要があります。

次に、`execution=cudaq.parallel.mpi` と設定することで、実行モードを指定します。以上の変更内容を示したのが、次のコードスニペットです。

```
cudaq.set_target("nvidia", option="mqpu")
cudaq.mpi.initialize()
result = cudaq.observe(
    kernel, hamiltonian, shots_count=n_shots, execution=cudaq.parallel.mpi
)
cudaq.mpi.finalize()
```

`hybrid_job` デコレータ内で、次のコードスニペットに示すように、複数の GPU をホストするインスタンスタイプを指定します。

```
@hybrid_job(
    device="local:nvidia/nvidia-mqpu",
    instance_config=InstanceConfig(instanceType="ml.g4dn.12xlarge", instanceCount=1),
    image_uri=image_uri,
)
def parallel_observables_gpu_job(sagemaker_mpi_enabled=True):
    ...
```

「Amazon Braket examples」Github の「[parallel simulations](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/nvidia_cuda_q/5_Multiple_GPU_simulations.ipynb)」ノートブックは、GPU バックエンドで量子プログラムシミュレーションを実行するとともにオブザーバブルと回路バッチの並列シミュレーションを実行する方法を示したエンドツーエンドのサンプルを提供しています。

### 量子コンピュータでワークロードを実行する
<a name="braket-using-cuda-q-quantum"></a>

シミュレーターのテストが完了したら、QPU での実験の実行に移ることができます。ターゲットを IQM、IonQ、または Rigetti デバイスなどの Amazon Braket QPU に切り替えるだけでよいのです。次のコードスニペットは、ターゲットを IQM Garnet デバイスに設定する方法を示しています。使用可能な QPU の一覧については、「[Amazon Braket console](https://console.aws.amazon.com/braket/home)」を参照してください。

```
device_arn = "arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet"
cudaq.set_target("braket", machine=device_arn)
```

ハイブリッドジョブの詳細については、「デベロッパーガイド」の「[Amazon Braket Hybrid Jobs の使用方法](braket-jobs.md)」を参照してください。CUDA-Q の詳細については、[NVIDIA CUDA-Q ドキュメント](https://nvidia.github.io/cuda-quantum/latest/index.html)を参照してください。