你当前正在访问 Microsoft Azure Global Edition 技术文档网站。 如果需要访问由世纪互联运营的 Microsoft Azure 中国技术文档网站,请访问 https://docs.azure.cn

如何管理会话

本文介绍如何管理会话。 使用会话,可以针对单个 target作业对一个或多个作业进行分组,这样就可以有效地管理作业。 有关详细信息,请参阅 会话入门。

先决条件

  • 具有活动订阅的 Azure 帐户。 如果没有 Azure 帐户,请免费注册并注册 即用即付订阅

  • Azure Quantum 工作区。 有关详细信息,请参阅创建 Azure Quantum 工作区

  • 安装了 Python 和 Pip 的 Python 环境。

  • Azure Quantum azure-quantum 包。 如果要使用 Qiskit 或 Cirq,则需要使用 [qiskit] 或 [cirq] 标记安装 azure-quantum 包。

    pip install --upgrade azure-quantum[qiskit] 
    

注意

会话使用 Python 进行管理,即使在运行 Q# 内联代码时也是如此。

监视会话

可以使用 Quantum 工作区中的“作业管理 ”边栏选项卡查看所有顶级提交的项,包括会话和未与任何会话关联的单个作业。

  1. Quantum 工作区中选择“作业管理 ”边栏选项卡。
  2. 标识会话类型的作业。 在此视图中,可以在列 ID 中看到会话的唯一 ID 并监视其 状态。 会话的状态为:
    • 正在等待:正在执行会话中的作业。
    • 成功:会话已成功结束。
    • TimeOut:如果未在会话内提交新作业 10 分钟,该会话将超时。有关详细信息,请参阅 会话超时
    • 失败:如果会话中的作业失败,该会话将结束并报告失败状态。 有关详细信息,请参阅 会话中的作业失败策略。
  3. 有关更多详细信息,请单击会话的名称。
  4. 可以查看会话中所有作业的列表并监视其状态。

检索和列出会话

下表显示了用于获取给定会话的所有会话和所有作业的列表的 Python 命令。

命令 说明
workspace.list_sessions()session.list_sessions() 检索 Quantum 工作区中所有会话的列表。
workspace.get_session(sessionId)session.get_session(sessionId) 检索 ID 为 <a0/a0> 的会话。 每个会话都具有唯一 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}")

打开/关闭会话的手动方法

建议按照会话入门中的步骤创建新会话。 还可以手动创建会话。

  1. 首先,创建 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}")
    

    注意

    此时,会话仅存在于客户端上,可以看到状态为 “无”。 若要查看会话的状态,还需要在服务中创建会话。

  2. 若要 在服务中创建 会话,可以使用 workspace.open_session(session)session.open()

  3. 可以使用会话 ID 刷新状态 和会话详细信息 session.refresh(),或者从会话 ID 获取新会话对象。

    same_session = workspace.get_session(session.id) 
    print(f"Session: {session.details} \n")
    print(f"Session: {same_session.details} \n")
    
  4. 可以使用workspace.close_session(session). 关闭会话session.close()

  5. 若要 将会话 附加到 a target,可以使用 target.latest_session

  6. 可以 等待 会话完成:

    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输入。

open Microsoft.Quantum.Measurement;
open Microsoft.Quantum.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 的状态。 若要避免这种情况,请使用添加块withbackend.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")