将本地代码作为混合作业运行 - Amazon Braket

通过以下方式学习量子计算的基础 AWS!注册 Amazon Braket 数字学习计划,完成一系列学习课程和数字评估后,即可获得自己的数字徽章。

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

将本地代码作为混合作业运行

Amazon Braket Hybrid Jobs 提供了混合量子经典算法的完全托管编排,将 Amazon EC2 计算资源与 Amazon Braket 量子处理单元 (QPU) 访问权限相结合。在混合作业中创建的量子任务优先于单个量子任务,因此您的算法不会因量子任务队列的波动而中断。每个 QPU 都维护一个单独的混合作业队列,确保在任何给定时间只能运行一个混合作业。

使用本地 Python 代码创建混合作业

你可以将本地 Python 代码作为 Amazon Braket Hybrid Job 运行。您可以通过使用@hybrid_job装饰器对代码进行注释来实现此目的,如以下代码示例所示。对于自定义环境,您可以选择使用 Amazon 弹性容器注册表 (ECR) 中的自定义容器。

注意

默认情况下,仅支持 Python 3.10。

你可以使用@hybrid_job装饰器来注释函数。Braket 将装饰器内部的代码转换为 Braket 混合作业算法脚本。然后,混合作业在 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装饰器中的 device 参数指定混合作业可以优先访问的设备,在本例中为SV1模拟器。要获得 QPU 优先级,必须确保函数中使用的设备 ARN 与装饰器中指定的设备 ARN 相匹配。为方便起见,您可以使用辅助函数get_job_device_arn()来捕获中声明的设备 ARN。@hybrid_job

注意

自从在 Amazon EC2 上创建容器化环境以来,每个混合任务至少有一分钟的启动时间。因此,对于非常短的工作负载,例如单个电路或一批电路,使用量子任务可能就足够了。

超级参数

run_hybrid_job()函数采用参数num_tasks来控制创建的量子任务的数量。混合作业会自动将其捕获为超参数

注意

超参数在 Braket 控制台中显示为字符串,限制为 2500 个字符。

指标和日志

run_hybrid_job()函数中,使用来记录来自迭代算法的log_metrics指标。指标会自动绘制在 Braket 控制台页面的 “混合作业” 选项卡下。在混合作业运行期间,您可以使用 Braket 成本跟踪器近乎实时地跟踪量子任务成本。上面的示例使用指标名称 “概率” 来记录结果类型的第一个概率。

正在检索结果

混合作业完成后,您可以使用job.result()检索混合作业的结果。Braket 会自动捕获返回语句中的任何对象。请注意,该函数返回的对象必须是一个元组,每个元素都是可序列化的。例如,以下代码显示了一个工作和一个失败的示例。

@hybrid_job(device=Devices.Amazon.SV1) def passing(): np_array = np.random.rand(5) return np_array # serializable @hybrid_job(device=Devices.Amazon.SV1) def failing(): return MyObject() # not serializable

Job 名称

默认情况下,此混合作业的名称是根据函数名称推断出来的。您也可以指定长度不超过 50 个字符的自定义名称。例如,在以下代码中,作业名称为 “my-job-name”。

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

本地模式

通过向装饰器添加参数local=True来创建@@ 本地作业。这将在本地计算环境(例如笔记本电脑)的容器化环境中运行混合作业。本地作业没有优先排队等候量子任务。对于多节点或 MPI 等高级案例,本地作业可以访问所需的 Braket 环境变量。以下代码使用设备作为 SV1 模拟器创建本地混合作业。

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

支持所有其他混合作业选项。有关选项列表,请参阅 braket.jobs. quantum_job_creation 模块。

安装其他 Python 软件包和源代码

您可以自定义运行时环境以使用首选的 Python 包。您可以使用requirements.txt文件、软件包名称列表或自带容器 (BYOC)。要使用requirements.txt文件自定义运行时环境,请参阅以下代码示例。

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

例如,该requirements.txt文件可能包含其他要安装的软件包。

qiskit pennylane >= 0.31 mitiq == 0.29

或者,您可以按如下方式以 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 ...

将数据保存并加载到混合作业实例中

指定输入训练数据

创建混合任务时,您可以通过指定亚马逊简单存储服务 (Amazon S3) 存储桶来提供输入训练数据集。您也可以指定本地路径,然后 Braket 会自动将数据上传到 Amazon S3,网址为。s3://<default_bucket_name>/jobs/<job_name>/<timestamp>/data/<channel_name>如果您指定本地路径,则频道名称默认为 “input”。以下代码显示了来自本地路径的 numpy 文件。data/file.npy

@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()辅助函数。

s3_path = "s3://amazon-braket-us-west-1-961591465522/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 或本地路径的字典来指定多个输入数据源。

input_data = { "input": "data/file.npy", "input_2": "s3://my-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 图。

@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此代码在名为 “checkpoints” 的子文件夹下的混合作业工件<jobname>.json中创建并覆盖具有默认名称的检查点文件。

要创建一个新的混合作业以从检查点继续,我们需要传递前一个作业的混合作业 ARN copy_checkpoints_from_job=job_arnjob_arn哪里。然后我们使用load_job_checkpoint(job_name)从检查点加载。

混合工作装饰者的最佳实践

拥抱异步性

使用 decorator 注释创建的混合作业是异步的,它们将在经典资源和量子资源可用后运行。您可以使用Braket Management Console或 Amazon 监控算法的进度 CloudWatch。当您提交算法以供运行时,Braket 会在可扩展的容器化环境中运行您的算法,并在算法完成后检索结果。

运行迭代变分算法

混合作业为你提供了运行迭代量子经典算法的工具。对于纯粹的量子问题,请使用量子任务或一批量子任务。优先访问某些 QPU 最有利于长时间运行的变分算法,这些算法需要对 QPU 进行多次迭代调用,中间有经典处理。

使用本地模式进行调试

在 QPU 上运行混合作业之前,建议先在模拟器 SV1 上运行以确认其按预期运行。对于小规模测试,可以在本地模式下运行,以实现快速迭代和调试。

使用自带容器 (BYOC) 提高可重复性

将您的软件及其依赖项封装在容器化环境中,从而创建可重现的实验。通过将所有代码、依赖项和设置打包到容器中,可以防止潜在的冲突和版本控制问题。

多实例分布式仿真器

要运行大量电路,可以考虑使用内置的 MPI 支持,在单个混合作业中的多个实例上运行本地模拟器。有关更多信息,请参阅嵌入式模拟器。

使用参数电路

您通过混合作业提交的参数电路会使用参数化编译在特定 QPU 上自动编译,以改善算法的运行时间。

定期检查点

对于长时间运行的混合作业,建议定期保存算法的中间状态。

有关更多示例、用例和最佳实践,请参阅 Amazon Bra GitHub ket 示例。