Vai al contenuto principale
Questo progetto è in fase beta. Hai trovato un bug? Apri una issue su GitHub. Hai una domanda o un'idea? Chiedi su GitHub Discussions — apprezziamo il tuo feedback!
Com'è la qualità della traduzione su questa pagina?

Supporto per l'accelerazione multi-processo e multi-thread

Questa pagina documenta in che misura qiskit-addon-sqd supporta l'accelerazione multi-thread e multi-processo, e le assunzioni su cui uno sviluppatore di calcolo ad alte prestazioni (HPC) può fare affidamento quando integra questo pacchetto in un carico di lavoro accelerato.

L'assunzione di thread singolo​

Salvo diversa indicazione, le API di questo pacchetto sono pensate per essere chiamate da un singolo thread. Le API di alto livello esposte da questo pacchetto non sono garantite come rientranti, e gli utenti finali non dovrebbero invocarle da alcun thread diverso dal thread principale.

Esecuzione collettiva multi-processo​

Questo pacchetto supporta l'accelerazione collettiva multi-processo nello stile single-program, multiple-data (SPMD), in cui l'intero programma viene avviato come più processi isolati che vengono eseguiti con sincronizzazione globale e comunicazione esplicite tra loro (ad esempio, mpirun -n 128 python my_program.py). Poiché lo stile SPMD si combina bene con gli scheduler di job e altro software parallelo e scala a un numero elevato di processi, è il modello raccomandato per i carichi di lavoro ad alte prestazioni e su larga scala, ed è l'argomento di questa pagina.

Sebbene questo pacchetto sia progettato per supportare diversi backend di esecuzione collettiva, la sua implementazione attuale è rivolta a MPI, l'API standard di message passing per i sistemi HPC. Indipendentemente dall'implementazione, questo pacchetto presuppone che un singolo thread controlli ciascun processo. Nel caso di MPI, ciò corrisponde a MPI_THREAD_FUNNELED o inferiore.

Se una funzione supporta l'esecuzione collettiva, la sua documentazione deve dirlo. Se la documentazione non menziona l'esecuzione collettiva, la funzione non ha semantica collettiva e deve essere chiamata solo dal processo di controllo.

La semantica specifica del valore di ritorno e della sincronizzazione di una funzione collettiva è documentata insieme alla funzione stessa. In generale, tale documentazione dovrebbe chiarire:

  • Se la funzione è pensata per essere chiamata indipendentemente da ciascun processo sui propri dati locali, oppure collettivamente da tutti i processi.

  • Come devono concordare i suoi argomenti tra i processi.

  • Come viene consegnato il suo valore di ritorno: se il risultato esiste solo sul processo di controllo, se tutti i processi ricevono lo stesso valore, oppure se ciascun processo riceve un handle a una porzione locale di una struttura dati distribuita.

Attualmente una sola funzione supporta la chiamata collettiva da tutti i processi: diagonalize_fermionic_hamiltonian(). Quando viene invocata collettivamente, la fase dell'eigensolver è quella in cui tutti i processi partecipano e contribuiscono con lavoro, quindi un'implementazione di eigensolver può usare ogni processo. Le restanti parti del ciclo di recupero delle configurazioni non hanno un'implementazione distribuita e vengono eseguite solo sul processo di controllo (rank 0).

Ogni sottospazio di un'iterazione viene passato all'eigensolver in una singola chiamata, quindi un'implementazione è libera di dividere i processi in gruppi e diagonalizzare più sottospazi in parallelo. Il modo in cui un risolutore usa i processi a sua disposizione è una proprietà di quell'eigensolver.

Alcune implementazioni di eigensolver esistenti richiedono che il programma chiamante venga eseguito al di fuori di un ambiente MPI/SPMD, perché avviano e gestiscono internamente i propri processi paralleli, ad esempio invocando mpirun per conto dell'utente. Questa modalità è comoda per il lavoro interattivo e basato su notebook e rimane supportata; i suoi requisiti per il programma chiamante sono descritti nel riferimento API della funzione diagonalize_fermionic_hamiltonian().

Gestione degli errori in un contesto multi-processo​

Una funzione chiamata collettivamente da tutti i processi non deve sollevare un'eccezione né interrompere un solo processo, perché ciò lascerebbe i processi rimanenti in deadlock o in uno stato incoerente. La gestione degli errori segue invece una semantica fail-stop per l'intero contesto di esecuzione: in caso di errore, l'implementazione deve essere pronta a interrompere collettivamente l'intero contesto di esecuzione (ad esempio, usando MPI_Abort).

L'API non può garantire una segnalazione coordinata degli errori né la consegna collettiva delle eccezioni tra i processi, perché le implementazioni di MPI non offrono tali garanzie. Un'implementazione potrebbe inoltre tentare di rendere un errore visibile a tutti i processi partecipanti, ad esempio facendo sollevare un'eccezione a ciascun processo, ma ciò può essere fornito solo secondo il principio del best effort e non deve essere usato come base per la correttezza o il recupero.

Queste sono proprietà che un'implementazione collettiva può avere, non garanzie su una particolare implementazione. In questo pacchetto, l'unico passo collettivo è l'eigensolver (vedi la sezione precedente); la sua implementazione predefinita non è distribuita, quindi queste considerazioni si applicano a un eigensolver collettivo personalizzato fornito dall'utente.