Come gestire le sessioni

Questo articolo illustra come gestire le sessioni. Con le sessioni, è possibile raggruppare uno o più processi rispetto a un singolo target, che consente di gestire in modo efficace i processi. Per altre informazioni, vedere Introduzione alle sessioni.

Prerequisiti

  • Un account Azure con una sottoscrizione attiva. Se non si ha un account Azure, registrarsi gratuitamente e iscriversi per ottenere una sottoscrizione con pagamento in base al consumo.

  • Un'area di lavoro di Azure Quantum. Per altre informazioni, vedere Creare un'area di lavoro di Azure Quantum.

  • Un ambiente Python con Python e Pip installati.

  • Pacchetto di Azure Quantum azure-quantum . Se si vuole usare Qiskit o Cirq, è necessario installare il azure-quantum pacchetto con i tag [qiskit] o [cirq].

    pip install --upgrade azure-quantum[qiskit] 
    

Nota

Le sessioni vengono gestite con Python, anche quando si esegue Q# codice inline.

Sessioni di monitoraggio

È possibile usare il pannello Gestione processi nell'area di lavoro Quantum per visualizzare tutti gli elementi inviati di primo livello, incluse le sessioni e i singoli processi non associati ad alcuna sessione.

  1. Selezionare il pannello Gestione processi nell'area di lavoro Quantum.
  2. Identificare i processi di tipo Session. In questa vista è possibile visualizzare l'ID univoco di una sessione nell'ID colonna e monitorarne lo stato. Gli stati di una sessione sono:
    • In attesa: i processi all'interno della sessione vengono eseguiti.
    • Operazione completata: la sessione è stata terminata correttamente.
    • TimeOut: se non viene inviato alcun nuovo processo all'interno della sessione per 10 minuti, si verifica il timeout della sessione. Per altre informazioni, vedere Timeout della sessione.
    • Operazione non riuscita: se un processo all'interno di una sessione ha esito negativo, la sessione termina e segnala lo stato Non riuscito. Per altre informazioni, vedere Criteri di errore del processo all'interno delle sessioni.
  3. Fare clic sul nome di una sessione per altri dettagli.
  4. È possibile visualizzare l'elenco Tutti i processi all'interno della sessione e monitorarne lo stato.

Recupero e presentazione di sessioni

La tabella seguente illustra i comandi Python per ottenere l'elenco di tutte le sessioni e di tutti i processi per una determinata sessione.

Comando Descrizione
workspace.list_sessions() oppure session.list_sessions() Recuperare un elenco di tutte le sessioni in un'area di lavoro quantistica.
workspace.get_session(sessionId) oppure session.get_session(sessionId) Recuperare la sessione con ID sessionId. Ogni sessione ha un ID univoco.
workspace.list_session_jobs(sessionId) oppure session.list_session_jobs(sessionId) Recuperare un elenco di tutti i processi nella sessione con ID sessionId. Ogni sessione ha un ID univoco.

Ad esempio, il codice seguente definisce una funzione che ottiene una sessione con un numero minimo di processi. Quindi, per tale sessione, elenca tutti i processi, il numero totale di processi e i primi 10 processi.

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

Metodi manuali di apertura/chiusura di sessioni

È consigliabile seguire la procedura descritta in Introduzione alle sessioni per creare una nuova sessione. È anche possibile creare manualmente sessioni.

  1. Creare prima di tutto un oggetto 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}")
    

    Nota

    A questo punto, la sessione esiste solo nel client e si può notare che lo stato è Nessuno. Per visualizzare lo stato della sessione, è anche necessario creare la sessione nel servizio.

  2. Per creare una sessione nel servizio, è possibile usare workspace.open_session(session) o session.open().

  3. È possibile aggiornare lo stato e i dettagli della sessione con session.refresh()o ottenendo un nuovo oggetto sessione da un ID sessione.

    same_session = workspace.get_session(session.id) 
    print(f"Session: {session.details} \n")
    print(f"Session: {same_session.details} \n")
    
  4. È possibile chiudere una sessione con session.close() o workspace.close_session(session).

  5. Per collegare la sessione a un targetoggetto , è possibile usare target.latest_session.

  6. È possibile attendere il completamento di una sessione:

    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)
    

Passaggio di argomenti in Q#

Se l'operazione Q# accetta argomenti di input, questi argomenti vengono passati durante l'invio del processo, ovvero codice Python. Ciò significa che è necessario prestare attenzione a formattare gli argomenti come Q# oggetti.

Quando si passano argomenti come parametri al processo, questi vengono formattati come Q# codice quando si chiama qsharp.compile, quindi i valori di Python devono essere formattati in una stringa come sintassi valida Q# .

Si consideri il programma seguente Q# , che accetta un numero intero, ne una matrice di angoli, angle, come input.

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;
}

Si vuole eseguire GenerateRandomBits l'operazione tre volte con n=2 e angoli diversi. È possibile usare il codice Python seguente per inviare tre processi con angoli diversi.

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]

In questo esempio, poiché le matrici in Python sono già stampate come [item0, item1, ...], gli argomenti di input corrispondono alla Q# formattazione. Per altre strutture di dati Python potrebbe essere necessaria una gestione maggiore per ottenere i valori stringa inseriti in Q# in modo compatibile. Ad esempio, una Q# tupla deve essere racchiusa tra parentesi con valori delimitati da virgole.

Timeout sessione

Si verifica il timeout di una sessione se non viene inviato alcun nuovo processo all'interno della sessione per 10 minuti. La sessione segnala lo stato di TimedOut. Per evitare questa situazione, aggiungere un with blocco usando backend.open_session(name="Name"), in modo che la sessione close() venga richiamata dal servizio alla fine del blocco di codice.

Nota

Se sono presenti errori o bug nel programma, potrebbero essere necessari più di 10 minuti per inviare un nuovo processo dopo il completamento dei processi precedenti nella sessione.

I frammenti di codice seguenti mostrano un esempio di timeout di una sessione dopo 10 minuti perché non vengono inviati nuovi processi. Per evitare questo problema, il frammento di codice successivo mostra come usare un with blocco per creare una sessione.

#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()

Criteri di errore del processo all'interno delle sessioni

Il criterio predefinito per una sessione quando un processo non riesce è terminare la sessione. Se si invia un processo aggiuntivo all'interno della stessa sessione, il servizio lo rifiuta e la sessione segnala lo stato Non riuscito. Tutti i processi in corso vengono annullati.

Tuttavia, questo comportamento può essere modificato specificando un criterio di errore del processo di job_failure_policy=SessionJobFailurePolicy.CONTINUE, anziché il valore predefinito SessionJobFailurePolicy.ABORT, durante la creazione della sessione. Quando i criteri di errore del processo sono CONTINUE, il servizio continua ad accettare processi. In questo caso, la sessione segnala uno stato di Errore , che verrà modificato in Non riuscito dopo la chiusura della sessione.

Se la sessione non viene mai chiusa e si verifica il timeout, lo stato è TimedOut anche se i processi non sono riusciti.

Ad esempio, il programma seguente crea una sessione con tre processi. Il primo processo ha esito negativo perché specifica "garbage" come dati di input. Per evitare la fine della sessione a questo punto, il programma mostra come aggiungere job_failure_policy=SessionJobFailurePolicy.CONTINUE durante la creazione della sessione.

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