

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 將本機程式碼執行為混合式任務
<a name="braket-hybrid-job-decorator"></a>

Amazon Braket Hybrid Jobs 提供混合量子傳統演算法的全受管協調，結合 Amazon EC2 運算資源與 Amazon Braket Quantum Processing Unit (QPU) 存取。在混合任務中建立的量子任務具有個別量子任務的優先順序佇列，因此您的演算法不會因量子任務佇列中的波動而中斷。每個 QPU 都會維護個別的混合式任務佇列，確保任何指定時間只能執行一個混合式任務。

**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_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。

```
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 符合裝飾項目中指定的 ARN。為了方便起見，您可以使用 協助程式函數`get_job_device_arn()`來擷取 中宣告的裝置 ARN`@hybrid_job`。

**注意**  
每個混合任務至少都有一分鐘的啟動時間，因為它會在 Amazon EC2 上建立容器化環境。因此，對於非常短的工作負載，例如單一電路或一批電路，它可能就足以讓您使用量子任務。

**超參數** 

`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)的第一個機率。

**擷取結果** 

混合任務完成後，您可以使用 `job.result()` 擷取混合任務結果。傳回陳述式中的任何物件都會由 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 模組。](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 會自動將資料上傳至`s3://<default_bucket_name>/jobs/<job_name>/<timestamp>/data/<channel_name>`位於 的 Amazon S3。如果您指定本機路徑，則頻道名稱預設為「輸入」。下列程式碼顯示來自本機路徑 的 numpy 檔案`data/file.npy`。

```
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()`協助程式 funciton。

```
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 URIs或本機路徑的字典來指定多個輸入資料來源。

```
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**

若要儲存未包含在裝飾函數的傳回陳述式中的結果，您必須將正確的目錄附加至所有檔案寫入操作。下列範例顯示儲存 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()` 會使用包含要儲存之資料的字典來呼叫 。根據預設，每個值都必須可序列化為文字。若要檢查點更複雜的 Python 物件，例如 numpy 陣列，您可以設定 `data_format = PersistedJobDataFormat.PICKLED_V4`。此程式碼會在稱為「檢查點」的子資料夾下，以混合任務成品`<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 監控演算法的進度。當您提交演算法以執行時，Raket 會在可擴展的容器化環境中執行演算法，並在演算法完成時擷取結果。

**執行反覆變化演算法**

混合任務為您提供執行反覆式量子傳統演算法的工具。對於純量子問題，請使用[量子任務](braket-submit-tasks.md)或一[批量子任務](braket-batching-tasks.md)。對特定 QPUs優先順序存取，對於需要對 QPUs 進行多次反覆呼叫並對其進行傳統處理的長時間執行變化演算法最有利。

**使用本機模式進行偵錯**

在 QPU 上執行混合任務之前，建議您先在模擬器 SV1 上執行，以確認它如預期般執行。對於小規模測試，您可以使用本機模式執行 ，以進行快速反覆運算和偵錯。

**使用[自有容器 (BYOC)](braket-jobs-byoc.md) 改善重現性**

在容器化環境中封裝您的軟體及其相依性，以建立可重現的實驗。透過在容器中封裝所有程式碼、相依性和設定，您可以防止潛在的衝突和版本控制問題。

**多執行個體分散式模擬器**

若要執行大量電路，請考慮使用內建的 MPI 支援，在單一混合任務中的多個執行個體上執行本機模擬器。如需詳細資訊，請參閱[內嵌模擬器](pennylane-embedded-simulators.md)。

**使用參數電路**

您從混合任務提交的參數電路會在特定 QPUs 上使用[參數編譯自動編譯](braket-jobs-parametric-compilation.md)，以改善演算法的執行時間。

**定期檢查點 **

對於長時間執行的混合任務，建議定期儲存演算法的中繼狀態。

**如需進一步的範例、使用案例和最佳實務，請參閱 [Amazon Braket 範例 GitHub](https://github.com/amazon-braket/amazon-braket-examples)。**