你当前正在访问 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 包,并且选择 qiskitcirq 的额外功能。

    pip install --upgrade azure-quantum[qiskit,cirq]
    

注释

即使运行内联代码Q#,会话也由Python管理。

监视用户会话

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

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

检索和列出会话

下表展示了 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}")

手动打开或关闭会话

若要创建新会话,最佳做法是遵循 会话入门中的步骤。 如果要改为手动创建会话,请选择开发环境的选项卡。

  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. 可以使用 刷新 session.refresh()和会话详细信息,或者使用会话 ID 获取新会话对象。

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

  5. 若要 将会话连接至 目标,可以使用 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输入。

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")