Suporte à aceleração em múltiplos processos e múltiplas threads
Esta página descreve até que ponto o [nome do pacote] oferece qiskit-addon-sqd suporte à aceleração multithread e multiprocesso, bem como os pressupostos nos quais um desenvolvedor de computação de alto desempenho (HPC) pode se basear ao integrar esse pacote a uma carga de trabalho acelerada.
A suposição de thread único
Salvo indicação em contrário, as APIs deste pacote devem ser chamadas a partir de uma única thread. Não se garante que as APIs de alto nível expostas por este pacote sejam reentrantes, e os usuários finais não devem invocá-las a partir de nenhuma thread que não seja a thread principal.
Execução coletiva de múltiplos processos
Este pacote oferece suporte à aceleração coletiva multiprocesso no estilo “programa único, dados múltiplos” (SPMD), no qual o programa inteiro é iniciado como múltiplos processos isolados que são executados com sincronização global explícita e comunicação entre eles (por exemplo, mpirun -n 128 python my_program.py). Como o estilo SPMD se integra perfeitamente a agendadores de tarefas e outros softwares paralelos e é escalável para um grande número de processos, ele é o modelo recomendado para cargas de trabalho de alto desempenho e em grande escala, sendo o tema desta página.
Embora esse pacote tenha sido projetado para acomodar diferentes back-ends de execução coletiva, sua implementação atual é voltada para o MPI, a API padrão de passagem de mensagens para sistemas de computação de alto desempenho (HPC). Independentemente da implementação, este pacote pressupõe que cada processo seja controlado por uma única thread. No caso do MPI, isso corresponde a MPI_THREAD_FUNNELED ou menos.
Se uma função suportar execução coletiva, sua documentação deve indicar isso. Se a documentação não mencionar a execução coletiva, a função não possui semântica coletiva e deve ser chamada apenas a partir do processo de controle.
O valor de retorno específico e a semântica de sincronização de uma função coletiva estão documentados na própria função. De modo geral, essa documentação deve deixar claro:
- Se a função deve ser chamada de forma independente por cada processo, utilizando seus próprios dados locais, ou de forma coletiva por todos os processos.
- Como seus argumentos devem ser consistentes entre os processos.
- Como o valor de retorno é fornecido — se o resultado existe apenas no processo de controle, se todos os processos recebem o mesmo valor ou se cada processo recebe um identificador para uma parte local de uma estrutura de dados distribuída.
Atualmente, apenas uma função permite ser chamada coletivamente por todos os processos: diagonalize_fermionic_hamiltonian(). Quando é executado de forma coletiva, a etapa do solucionador de valores próprios é aquela em que todos os processos participam e contribuem com trabalho; portanto, uma implementação do solucionador de valores próprios pode utilizar todos os processos. As demais partes do ciclo de recuperação de configuração não possuem implementação distribuída e são executadas apenas no processo de controle (rank 0).
Algumas implementações existentes de solucionadores de valores próprios, por outro lado, exigem que o programa chamador seja executado fora de um ambiente MPI/SPMD, pois elas iniciam e gerenciam seus próprios processos paralelos internamente, por exemplo, chamando mpirun em nome do usuário. Esse modo é prático para trabalhos interativos e em cadernos de anotações e continua sendo suportado; seus requisitos em relação ao programa chamador estão descritos na referência da API da função diagonalize_fermionic_hamiltonian() .
Tratamento de erros em um contexto multiprocessos
Uma função que é chamada coletivamente por todos os processos não deve gerar uma exceção nem interromper apenas um único processo, pois isso deixaria os processos restantes em impasse ou em um estado inconsistente. Em vez disso, o tratamento de erros segue a semântica “fail-stop” para o contexto de execução como um todo: ao ocorrer um erro, a implementação deve estar preparada para interromper todo o contexto de execução de uma só vez (por exemplo, utilizando MPI_Abort).
A API não pode garantir o relato coordenado de erros nem a transmissão coletiva de exceções entre processos, pois as implementações do MPI não oferecem tais garantias. Uma implementação pode, além disso, tentar tornar um erro visível a todos os processos participantes — por exemplo, fazendo com que cada processo gere uma exceção —, mas isso só pode ser garantido na medida do possível e não deve ser considerado como garantia de correção ou recuperação.
Essas são características que uma implementação coletiva pode apresentar, e não garantias em relação a qualquer uma delas em particular. Neste pacote, a única etapa coletiva é o solucionador de valores próprios (consulte a seção anterior); sua implementação padrão não é distribuída, portanto, essas considerações se aplicam a um solucionador de valores próprios coletivo personalizado fornecido pelo usuário.