Execute cargas de trabalho híbridas com PennyLane simuladores incorporados - Amazon Braket

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Execute cargas de trabalho híbridas com PennyLane simuladores incorporados

Vamos ver como você pode usar simuladores incorporados do PennyLane Amazon Braket Hybrid Jobs para executar cargas de trabalho híbridas. O simulador incorporado GPU baseado em Pennylane,lightning.gpu, usa a cuQuantum biblioteca Nvidia para acelerar as simulações de circuitos. O GPU simulador incorporado é pré-configurado em todos os contêineres de trabalho do Braket que os usuários podem usar imediatamente. Nesta página, mostramos como usar lightning.gpu para acelerar suas cargas de trabalho híbridas.

Usando lightning.gpu para QAOA cargas de trabalho

Considere os exemplos do algoritmo de otimização aproximada quântica (QAOA) deste notebook. Para selecionar um simulador incorporado, você especifica o device argumento para ser uma string no formato:"local:<provider>/<simulator_name>". Por exemplo, você definiria "local:pennylane/lightning.gpu" paralightning.gpu. A string do dispositivo que você fornece ao Hybrid Job ao iniciar é passada para o trabalho como a variável de ambiente"AMZN_BRAKET_DEVICE_ARN".

device_string = os.environ["AMZN_BRAKET_DEVICE_ARN"] prefix, device_name = device_string.split("/") device = qml.device(simulator_name, wires=n_wires)

Nesta página, vamos comparar os dois simuladores de vetores de PennyLane estado incorporados lightning.qubit (que são CPU baseados) e lightning.gpu (que são GPU baseados). Você precisará fornecer aos simuladores algumas decomposições de portas personalizadas para calcular vários gradientes.

Agora você está pronto para preparar o script híbrido de lançamento de trabalhos. Você executará o QAOA algoritmo usando dois tipos de instância: m5.2xlarge p3.2xlarge e. O tipo de m5.2xlarge instância é comparável a um laptop padrão para desenvolvedores. p3.2xlargeÉ uma instância de computação acelerada que tem um único NVIDIA Volta GPU com 16 GB de memória.

O hyperparameters para todos os seus trabalhos híbridos será o mesmo. Tudo o que você precisa fazer para experimentar diferentes instâncias e simuladores é alterar duas linhas da seguinte forma.

# Specify device that the hybrid job will primarily be targeting device = "local:pennylane/lightning.qubit" # Run on a CPU based instance with about as much power as a laptop instance_config = InstanceConfig(instanceType='ml.m5.2xlarge')

ou:

# Specify device that the hybrid job will primarily be targeting device = "local:pennylane/lightning.gpu" # Run on an inexpensive GPU based instance instance_config = InstanceConfig(instanceType='ml.p3.2xlarge')
nota

Se você especificar o instance_config como usando uma instância GPU baseada, mas escolher o device para ser o simulador CPU baseado em incorporação (lightning.qubit), o não GPU será usado. Certifique-se de usar o GPU simulador incorporado se desejar atingir o! GPU

Primeiro, você pode criar duas tarefas híbridas e resolver o Max-Cut QAOA em um gráfico com 18 vértices. Isso se traduz em um circuito de 18 qubits, relativamente pequeno e viável de ser executado rapidamente em seu laptop ou na instância. m5.2xlarge

num_nodes = 18 num_edges = 24 seed = 1967 graph = nx.gnm_random_graph(num_nodes, num_edges, seed=seed) # And similarly for the p3 job m5_job = AwsQuantumJob.create( device=device, source_module="qaoa_source", job_name="qaoa-m5-" + str(int(time.time())), image_uri=image_uri, # Relative to the source_module entry_point="qaoa_source.qaoa_algorithm_script", copy_checkpoints_from_job=None, instance_config=instance_config, # general parameters hyperparameters=hyperparameters, input_data={"input-graph": input_file_path}, wait_until_complete=True, )

O tempo médio de iteração para a m5.2xlarge instância é de cerca de 25 segundos, enquanto para a p3.2xlarge instância é de cerca de 12 segundos. Para esse fluxo de trabalho de 18 qubits, a GPU instância nos dá uma aceleração de 2x. Se você olhar a página de preços do Amazon Braket Hybrid Jobs, verá que o custo por minuto para m5.2xlarge uma instância é de 0,00768 USD, enquanto para a instância é de 0,06375 USD. p3.2xlarge Executar um total de 5 iterações, como você fez aqui, custaria 0,016 USD usando a CPU instância ou 0,06375 USD usando a instância — ambas muito baratas! GPU

Agora vamos dificultar o problema e tentar resolver um problema de Max-Cut em um gráfico de 24 vértices, que se traduzirá em 24 qubits. Execute as tarefas híbridas novamente nas mesmas duas instâncias e compare o custo.

nota

Você verá que o tempo para executar esse trabalho híbrido na CPU instância pode ser de cerca de cinco horas!

num_nodes = 24 num_edges = 36 seed = 1967 graph = nx.gnm_random_graph(num_nodes, num_edges, seed=seed) # And similarly for the p3 job m5_big_job = AwsQuantumJob.create( device=device, source_module="qaoa_source", job_name="qaoa-m5-big-" + str(int(time.time())), image_uri=image_uri, # Relative to the source_module entry_point="qaoa_source.qaoa_algorithm_script", copy_checkpoints_from_job=None, instance_config=instance_config, # general parameters hyperparameters=hyperparameters, input_data={"input-graph": input_file_path}, wait_until_complete=True, )

O tempo médio de iteração para a m5.2xlarge instância é de aproximadamente uma hora, enquanto para a p3.2xlarge instância é de aproximadamente dois minutos. Para esse problema maior, a GPU instância é uma ordem de magnitude mais rápida! Tudo o que você precisava fazer para se beneficiar dessa aceleração era alterar duas linhas de código, trocando o tipo de instância e o simulador local usado. Executar um total de 5 iterações, como foi feito aqui, custaria cerca de 2,27072 USD usando a CPU instância ou cerca de 0,775625 USD usando a instância. GPU O CPU uso não é apenas mais caro, mas também leva mais tempo para ser executado. Acelerar esse fluxo de trabalho com uma GPU instância disponível AWS, usando o PennyLane simulador incorporado apoiado por NVIDIA CuQuantum, permite que você execute fluxos de trabalho com contagens intermediárias de qubits (entre 20 e 30) por menos custo total e em menos tempo. Isso significa que você pode experimentar a computação quântica até mesmo para problemas grandes demais para serem executados rapidamente em seu laptop ou em uma instância de tamanho similar.

Aprendizado de máquina quântico e paralelismo de dados

Se seu tipo de carga de trabalho for aprendizado de máquina quântico (QML) treinado em conjuntos de dados, você poderá acelerar ainda mais sua carga de trabalho usando o paralelismo de dados. EmQML, o modelo contém um ou mais circuitos quânticos. O modelo também pode ou não conter redes neurais clássicas. Ao treinar o modelo com o conjunto de dados, os parâmetros no modelo são atualizados para minimizar a função de perda. Uma função de perda geralmente é definida para um único ponto de dados e a perda total para a perda média em todo o conjunto de dados. EmQML, as perdas geralmente são calculadas em série antes da média da perda total para cálculos de gradiente. Esse procedimento é demorado, especialmente quando há centenas de pontos de dados.

Como a perda de um ponto de dados não depende de outros pontos de dados, as perdas podem ser avaliadas paralelamente! Perdas e gradientes associados a diferentes pontos de dados podem ser avaliados ao mesmo tempo. Isso é conhecido como paralelismo de dados. Com SageMaker a biblioteca paralela de dados distribuídos, o Amazon Braket Hybrid Jobs facilita a utilização do paralelismo de dados para acelerar seu treinamento.

Considere a seguinte QML carga de trabalho para paralelismo de dados, que usa o conjunto de dados Sonar do conhecido UCI repositório como exemplo de classificação binária. O conjunto de dados Sonar tem 208 pontos de dados, cada um com 60 características que são coletadas de sinais de sonar refletidos em materiais. Cada ponto de dados é rotulado como “M” para minas ou “R” para rochas. Nosso QML modelo consiste em uma camada de entrada, um circuito quântico como camada oculta e uma camada de saída. As camadas de entrada e saída são redes neurais clássicas implementadas em PyTorch. O circuito quântico é integrado às PyTorch redes neurais usando PennyLane o módulo qml.qnn. Veja nossos exemplos de notebooks para obter mais detalhes sobre a carga de trabalho. Como no QAOA exemplo acima, você pode aproveitar o poder de GPU usar simuladores incorporados como GPU PennyLane os nossos lightning.gpu para melhorar o desempenho em relação aos simuladores incorporadosCPU.

Para criar uma tarefa híbrida, você pode chamar AwsQuantumJob.create e especificar o script do algoritmo, o dispositivo e outras configurações por meio de seus argumentos de palavra-chave.

instance_config = InstanceConfig(instanceType='ml.p3.2xlarge') hyperparameters={"nwires": "10", "ndata": "32", ... } job = AwsQuantumJob.create( device="local:pennylane/lightning.gpu", source_module="qml_source", entry_point="qml_source.train_single", hyperparameters=hyperparameters, instance_config=instance_config, ... )

Para usar o paralelismo de dados, você precisa modificar algumas linhas de código no script do algoritmo da biblioteca SageMaker distribuída para paralelizar corretamente o treinamento. Primeiro, você importa o smdistributed pacote que faz a maior parte do trabalho pesado para distribuir suas cargas de trabalho em várias e várias GPUs instâncias. Este pacote é pré-configurado no Braket PyTorch e nos contêineres. TensorFlow O dist módulo informa ao nosso script de algoritmo qual é o número total de GPUs para o treinamento (world_size), bem como o rank final local_rank de um GPU núcleo. ranké o índice absoluto de a GPU em todas as instâncias, enquanto local_rank é o índice de a GPU dentro de uma instância. Por exemplo, se houver quatro instâncias, cada uma com oito GPUs alocadas para o treinamento, os rank intervalos variam de 0 a 31 e os local_rank intervalos de 0 a 7.

import smdistributed.dataparallel.torch.distributed as dist dp_info = { "world_size": dist.get_world_size(), "rank": dist.get_rank(), "local_rank": dist.get_local_rank(), } batch_size //= dp_info["world_size"] // 8 batch_size = max(batch_size, 1)

Em seguida, você define um de DistributedSampler acordo com o world_size rank e, em seguida, o passa para o carregador de dados. Esse amostrador evita GPUs acessar a mesma fatia de um conjunto de dados.

train_sampler = torch.utils.data.distributed.DistributedSampler( train_dataset, num_replicas=dp_info["world_size"], rank=dp_info["rank"] ) train_loader = torch.utils.data.DataLoader( train_dataset, batch_size=batch_size, shuffle=False, num_workers=0, pin_memory=True, sampler=train_sampler, )

Em seguida, você usa a DistributedDataParallel classe para ativar o paralelismo de dados.

from smdistributed.dataparallel.torch.parallel.distributed import DistributedDataParallel as DDP model = DressedQNN(qc_dev).to(device) model = DDP(model) torch.cuda.set_device(dp_info["local_rank"]) model.cuda(dp_info["local_rank"])

As alterações acima são necessárias para usar o paralelismo de dados. EmQML, você geralmente deseja salvar os resultados e imprimir o progresso do treinamento. Se cada um GPU executar o comando de salvar e imprimir, o registro será inundado com as informações repetidas e os resultados se substituirão. Para evitar isso, você só pode salvar e imprimir a partir do GPU que tem rank 0.

if dp_info["rank"]==0: print('elapsed time: ', elapsed) torch.save(model.state_dict(), f"{output_dir}/test_local.pt") save_job_result({"last loss": loss_before})

O Amazon Braket Hybrid Jobs ml.p3.16xlarge oferece suporte a tipos de instância para a biblioteca paralela de dados SageMaker distribuídos. Você configura o tipo de instância por meio do InstanceConfig argumento em Hybrid Jobs. Para que a biblioteca paralela de dados SageMaker distribuídos saiba que o paralelismo de dados está ativado, você precisa adicionar dois hiperparâmetros adicionais, "sagemaker_distributed_dataparallel_enabled" configurando "true" e "sagemaker_instance_type" configurando o tipo de instância que você está usando. Esses dois hiperparâmetros são usados por smdistributed pacote. Seu script de algoritmo não precisa usá-los explicitamente. No Amazon SDK Braket, ele fornece um argumento de palavra-chave conveniente. distribution Com a criação distribution="data_parallel" de empregos híbridos, o Amazon SDK Braket insere automaticamente os dois hiperparâmetros para você. Se você usa o Amazon API Braket, precisa incluir esses dois hiperparâmetros.

Com o paralelismo de instâncias e dados configurados, agora você pode enviar seu trabalho híbrido. Há 8 GPUs em uma ml.p3.16xlarge instância. Quando você defineinstanceCount=1, a carga de trabalho é distribuída entre os 8 GPUs na instância. Quando você define instanceCount mais de um, a carga de trabalho é distribuída entre os GPUs disponíveis em todas as instâncias. Ao usar várias instâncias, cada instância incorre em uma cobrança com base no tempo de uso. Por exemplo, quando você usa quatro instâncias, o tempo faturável é quatro vezes o tempo de execução por instância, pois há quatro instâncias executando suas cargas de trabalho ao mesmo tempo.

instance_config = InstanceConfig(instanceType='ml.p3.16xlarge', instanceCount=1, ) hyperparameters={"nwires": "10", "ndata": "32", ..., } job = AwsQuantumJob.create( device="local:pennylane/lightning.gpu", source_module="qml_source", entry_point="qml_source.train_dp", hyperparameters=hyperparameters, instance_config=instance_config, distribution="data_parallel", ... )
nota

Na criação de empregos híbridos acima, train_dp.py está o script de algoritmo modificado para usar o paralelismo de dados. Lembre-se de que o paralelismo de dados só funciona corretamente quando você modifica seu script de algoritmo de acordo com a seção acima. Se a opção de paralelismo de dados for ativada sem um script de algoritmo modificado corretamente, a tarefa híbrida poderá gerar erros ou cada uma GPU poderá processar repetidamente a mesma fatia de dados, o que é ineficiente.

Vamos comparar o tempo de execução e o custo em um exemplo em que ao treinar um modelo com um circuito quântico de 26 qubits para o problema de classificação binária mencionado acima. A ml.p3.16xlarge instância usada neste exemplo custa 0,4692 USD por minuto. Sem paralelismo de dados, o simulador leva cerca de 45 minutos para treinar o modelo por 1 época (ou seja, mais de 208 pontos de dados) e custa cerca de $20. Com o paralelismo de dados em 1 instância e 4 instâncias, são necessários apenas 6 minutos e 1,5 minutos, respectivamente, o que significa aproximadamente 2,8 USD para ambas. Ao usar o paralelismo de dados em 4 instâncias, você não apenas melhora o tempo de execução em 30 vezes, mas também reduz os custos em uma ordem de magnitude!