你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn。
在其中 Azure Quantum,可以针对单个目标对多个作业进行分组,以有效地管理作业。 这称为会话。 有关详细信息,请参阅 会话入门。
本文介绍如何使用会话手动管理作业。 你还将了解作业失败处理策略以及如何避免会话超时。
先决条件
拥有有效订阅的 Azure 帐户。 如果没有 Azure 帐户,请免费注册并注册 即用即付订阅。
一个工作区 Azure Quantum 。 有关详细信息,请参阅 “创建 Azure Quantum 工作区”。
安装了 Python 的 Python 环境。
包
azure-quantumPython 。 如果你想使用 Qiskit 或者 Cirq ,那么需要安装azure-quantum包,并且选择qiskit或cirq的额外功能。pip install --upgrade azure-quantum[qiskit,cirq]
注释
即使运行内联代码Q#,会话也由Python管理。
监视用户会话
可以使用 Quantum 工作区中的 “作业管理”面板 查看所有顶层提交项,包括会话和未与任何会话关联的单个作业。
- 在 Quantum 工作区中选择 “作业管理”边栏。
- 标识 会话类型的作业。 在此视图中,可以在 ID 列中找到会话的唯一 ID,并监视会话 的状态。 会话可以具有以下状态:
- 等待中:会话中的作业当前正在运行。
- 成功:会话已成功结束。
- TimeOut:如果未在会话内提交新作业 10 分钟,则该会话超时。有关详细信息,请参阅 会话超时。
- 失败:如果会话中的作业失败,则该会话将结束并报告 失败状态。 有关详细信息,请参阅 会话中的作业失败策略。
- 单击会话名称以获得更多详细信息。
- 可以查看会话中 所有作业 的列表并监视其状态。
检索和列出会话
下表展示了 Python 命令,用于获取所有会话及给定会话的所有作业列表。
| Command | Description |
|---|---|
workspace.list_sessions() 或 session.list_sessions() |
检索 Quantum 工作区中所有会话的列表。 |
workspace.get_session(sessionId) 或 session.get_session(sessionId) |
检索 ID 为 sessionId 的会话。 每个会话都具有唯一 ID。 |
workspace.list_session_jobs(sessionId) 或 session.list_session_jobs(sessionId) |
获取ID sessionId 的会话中的所有任务列表。 每个会话都具有唯一 ID。 |
例如,以下代码定义一个获取作业数量最少的会话的函数。 然后,在该会话中,它会列出所有作业、作业的总数以及前 10 个作业。
def get_a_session_with_jobs(min_jobs):
all_sessions = workspace.list_sessions() # list of all sessions
for session in all_sessions:
if len(workspace.list_session_jobs(session.id)) >= min_jobs:
return session
session = get_a_session_with_jobs(min_jobs=3) # Get a Session with at least 3 jobs
session_jobs = workspace.list_session_jobs(session.id) # List of all jobs within Session ID
print(f"Job count: {len(session_jobs)} \n")
print(f"First 10 jobs for session {session.id}:")
for job in session_jobs[0:10]:
print(f"Id: {job.id}, Name={job.details.name}")
手动打开或关闭会话
若要创建新会话,最佳做法是遵循 会话入门中的步骤。 如果要改为手动创建会话,请选择开发环境的选项卡。
创建 Session 对象。
from azure.quantum.job.session import Session, SessionDetails, SessionJobFailurePolicy import uuid session = Session( workspace=workspace, # required id=f"{uuid.uuid1()}", # optional, if not passed will use uuid.uuid1() name="", # optional, will be blank if not passed provider_id="ionq", # optional, if not passed will try to parse from the target target="ionq.simulator", # required job_failure_policy=SessionJobFailurePolicy.ABORT # optional, defaults to abort ) print(f"Session status: {session.details.status}")注释
此时,会话仅存在于客户端上,可以看到状态为 “无”。 若要查看会话的状态,还需要在服务中创建会话。
若要在服务 中创建 会话,可以使用
workspace.open_session(session)或session.open()。可以使用 刷新
session.refresh()和会话详细信息,或者使用会话 ID 获取新会话对象。same_session = workspace.get_session(session.id) print(f"Session: {session.details} \n") print(f"Session: {same_session.details} \n")可以使用
或 关闭会话 。 若要 将会话连接至 目标,可以使用
target.latest_session。可以 等待 会话完成:
session_jobs = session.list_jobs() [session_job.id for session_job in session_jobs] import time while (session.details.status != "Succeeded" and session.details.status != "Failed" and session.details.status != "TimedOut"): session.refresh() time.sleep(5)
传入参数 Q#
Q#如果操作需要输入参数,则这些参数会在作业提交期间通过Python代码传递。 这意味着需要将参数的格式设置为 Q# 对象。
当您将参数作为参数传递给作业时,这些参数会在调用qsharp.compile之前被格式化为Q#代码,因此需要将Python中的值格式化成包含有效Q#语法的字符串。
请考虑以下 Q# 程序,它采用整数 n和角度数组作为 angle输入。
import Std.Measurement.*;
import Std.Arrays.*;
operation GenerateRandomBits(n: Int, angle: Double[]) : Result[] {
use qubits = Qubit[n]; // n parameter as the size of the qubit array
for q in qubits {
H(q);
}
R(PauliZ, angle[0], qubits[0]); // arrays as entry-points parameters
R(PauliZ, angle[1], qubits[1]);
let results = MeasureEachZ(qubits);
ResetAll(qubits);
return results;
}
你想将 GenerateRandomBits 操作运行三次,并且使用不同的 n=2 角度。 可以使用以下 Python 代码提交具有不同角度的三个作业。
angle = [0.0, 0.0]
with target.open_session(name="Q# session of three jobs") as session:
target.submit(input_data=qsharp.compile(f"GenerateRandomBits(2, {angle})"), name="Job 1", shots=100) # First job submission
angle[0] += 1
target.submit(input_data=qsharp.compile(f"GenerateRandomBits(2, {angle})"), name="Job 2", shots=100) # Second job submission
angle[1] += 1
target.submit(input_data=qsharp.compile(f"GenerateRandomBits(2, {angle})"), name="Job 3", shots=100) # Third job submission
session_jobs = session.list_jobs()
[session_job.details.name for session_job in session_jobs]
在此示例中,由于数组 Python 已打印为 [item0, item1, ...],因此输入参数与格式匹配 Q# 。 对于其他 Python 数据结构,可能需要进行更多处理才能以兼容的方式插入 Q# 字符串值。 例如, Q# 元组必须位于带逗号分隔值的括号中。
会话超时
如果会话内在 10 分钟内未提交新作业,则会话超时。 会话报告状态为TimedOut。 为了避免这种情况,请使用with添加backend.open_session(name="Name")块,以便服务在代码块末尾调用close()会话。
注释
如果程序中存在错误或 bug,则在当前会话中的所有作业完成后,提交新作业可能需要 10 分钟以上的时间。
以下代码片段显示了会话示例,该会话在 10 分钟后超时,因为未提交任何新作业。 为了避免这种情况,下一个代码片段演示如何使用 with 块创建会话。
#Example of a session that times out
session = backend.open_session(name="Qiskit circuit session") # Session times out because only contains one job
backend.run(circuit=circuit, shots=100, job_name="Job 1")
#Example of a session that includes a with block to avoid timeout
with backend.open_session(name="Qiskit circuit session") as session: # Use a with block to submit multiple jobs within a session
job1 = backend.run(circuit=circuit, shots=100, job_name="Job 1") # First job submission
job1.wait_for_final_state()
job2 = backend.run(circuit=circuit, shots=100, job_name="Job 2") # Second job submission
job2.wait_for_final_state()
job3 = backend.run(circuit=circuit, shots=100, job_name="Job 3") # Third job submission
job3.wait_for_final_state()
会话中的作业失败策略
作业失败时会话的默认策略是结束该会话。 如果在同一会话中提交其他作业,服务将拒绝该作业,并且会话报告 失败状态。 任何正在进行的作业将被取消。
但是,创建会话时,可以通过指定作业失败策略 job_failure_policy=SessionJobFailurePolicy.CONTINUE(而不是默认值 SessionJobFailurePolicy.ABORT)来更改此行为。 当作业失败策略为 CONTINUE 时,服务会继续接受作业。 在这种情况下,会话报告 失败 状态,该状态将在会话关闭后更改为 “失败 ”。
如果会话从未关闭且超时,则即使作业失败,状态也为 TimedOut 。
例如,以下程序创建具有三个任务的会话。 第一个作业失败,因为它指定 "garbage" 为输入数据。 为了避免此时结束会话,程序演示如何在创建会话时添加 job_failure_policy=SessionJobFailurePolicy.CONTINUE 。
#Example of a session that does not close but reports Failure(s) when a jobs fails
with target.open_session(name="JobFailurePolicy Continue", job_failure_policy=SessionJobFailurePolicy.CONTINUE) as session:
target.submit(input_data="garbage", name="Job 1") #Input data is missing, this job fails
target.submit(input_data=quil_program, name="Job 2") #Subsequent jobs are accepted because of CONTINUE policy
target.submit(input_data=quil_program, name="Job 3")