セッションを管理する方法

この記事では、セッションを管理する方法について説明します。 セッションを使用すると、1 つの targetに対して 1 つ以上のジョブをグループ化できるため、ジョブを効果的に管理できます。 詳細については、「 セッションの開始」を参照してください。

前提条件

Note

インライン コードを実行している場合でも、セッションは Python で管理 Q# 。

セッションの監視

Quantum ワークスペースの [ ジョブ管理 ] ブレードを使用すると、セッションやセッションに関連付けられていない個々のジョブなど、最上位レベルで送信されたすべてのアイテムを表示できます。

  1. Quantum ワークスペースで Job management ブレードを選択します。
  2. Sessionの種類のジョブを識別します。 このビューでは、列 Id のセッションの一意の ID を確認し、その Statusを監視できます。 セッションの状態は次のとおりです。
    • 待機中: セッション内のジョブが実行されています。
    • 成功: セッションは正常に終了しました。
    • TimeOut: セッション内で 10 分間新しいジョブが送信されない場合、そのセッションはタイムアウトします。詳細については、「 Session timeouts」を参照してください。
    • 失敗: セッション内のジョブが失敗した場合、そのセッションは終了し、 Failedの状態が報告されます。 詳細については、「セッション内のジョブの失敗ポリシーを参照してください。
  3. 詳細については、セッションの名前をクリックしてください。
  4. セッション内で すべてのジョブ の一覧を表示し、その状態を監視できます。

セッションの取得と一覧表示

次の表に、特定のセッションのすべてのセッションとすべてのジョブの一覧を取得する Python コマンドを示します。

command 説明
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}")

セッションを開く/閉じる手動の方法

新しいセッションを作成するには、「 Get started with sessions 」の手順に従うことをお勧めします。 セッションを手動で作成することもできます。

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

    Note

    この時点で、セッションはクライアントにのみ存在し、状態が None であることがわかります。 セッションの状態を表示するには、サービスでセッションを作成する必要もあります。

  2. サービス内のセッションを 作成 するには、 workspace.open_session(session) または session.open()を使用できます。

  3. statusとセッションの詳細をsession.refresh()で更新するか、セッション ID から新しいセッション オブジェクトを取得します。

    same_session = workspace.get_session(session.id) 
    print(f"Session: {session.details} \n")
    print(f"Session: {same_session.details} \n")
    
  4. session.close()またはworkspace.close_session(session)とのセッション閉じるできます。

  5. セッションを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#構文として文字列に書式設定する必要があります。

整数、n、および角度の配列を入力として受け取る次のQ# プログラム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;
}

n=2と異なる角度GenerateRandomBits操作を 3 回実行する必要があります。 次の Python コードを使用して、異なる角度で 3 つのジョブを送信できます。

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 の状態を報告します。 このような状況を回避するには、backend.open_session(name="Name")を使用してwith ブロックを追加し、コード ブロックの最後にサービスによってセッション close()が呼び出されるようにします。

Note

プログラムにエラーやバグがある場合は、セッション内の前のジョブがすべて完了した後、新しいジョブを送信するのに 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()

セッション内のジョブ エラー ポリシー

ジョブが失敗した場合のセッションの既定のポリシーは、そのセッションを終了することです。 同じセッション内で追加のジョブを送信すると、サービスはそれを拒否し、セッションは Failed の状態を報告します。 進行中のジョブはすべて取り消されます。

ただし、この動作は、セッションの作成時に既定のSessionJobFailurePolicy.ABORTではなく、job_failure_policy=SessionJobFailurePolicy.CONTINUEのジョブエラー ポリシーを指定することで変更できます。 ジョブエラー ポリシーが CONTINUEされると、サービスはジョブを引き続き受け入れます。 この場合、セッションは Failure(s) の状態を報告します。この状態は、セッションが閉じられると Failed に変わります。

セッションが閉じずにタイムアウトになった場合、ジョブが失敗した場合でも、状態は TimedOut になります。

たとえば、次のプログラムは、3 つのジョブを含むセッションを作成します。 最初のジョブは、入力データとして "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")