Acelere suas cargas de trabalho híbridas com simuladores incorporados da PennyLane - 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á.

Acelere suas cargas de trabalho híbridas com simuladores incorporados da PennyLane

Vamos ver como você pode usar simuladores incorporados do PennyLane Amazon Braket Hybrid Jobs para executar cargas de trabalho híbridas. O simulador incorporado baseado em GPU da Pennylane,lightning.gpu, usa a biblioteca Nvidia CuQuantum para acelerar as simulações de circuitos. O simulador de GPU 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 cargas de trabalho do algoritmo de otimização aproximada quântica

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 baseados em CPU) e lightning.gpu (que são baseados em GPU). 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 algoritmo QAOA usando dois tipos de instância: e. m5.2xlarge p3.2xlarge 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 uma única GPU NVIDIA Volta 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 baseada em GPU, mas escolher o device para ser o simulador baseado em CPU incorporado (lightning.qubit), a GPU não será usada. Certifique-se de usar o simulador incorporado baseado em GPU se quiser atingir a GPU!

Primeiro, você pode criar duas tarefas híbridas e resolver Max-Cut com 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 instância da GPU 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 instância de CPU ou 0,06375 USD usando a instância de GPU — ambas bem baratas!

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 instância da CPU 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 instância da GPU é 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 instância de CPU ou cerca de 0,775625 USD usando a instância de GPU. O uso da CPU não é apenas mais caro, mas também leva mais tempo para ser executado. Acelerar esse fluxo de trabalho com uma instância de GPU disponível AWS, usando o simulador incorporado PennyLane da 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. No QML, 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. Em QML, 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 carga de trabalho QML para paralelismo de dados, que usa o conjunto de dados Sonar do conhecido repositório UCI 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 modelo QML 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 exemplo de QAOA acima, você pode aproveitar o poder da GPU usando simuladores incorporados baseados em GPU, como PennyLane os nossos, lightning.gpu para melhorar o desempenho em relação aos simuladores baseados em CPU incorporada.

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 GPUs e várias 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 núcleo de GPU. ranké o índice absoluto de uma GPU em todas as instâncias, enquanto local_rank é o índice de uma GPU dentro de uma instância. Por exemplo, se houver quatro instâncias, cada uma com oito GPUs alocadas para o treinamento, isso rank varia de 0 a 31 e local_rank varia 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 que as GPUs acessem 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. Em QML, você geralmente deseja salvar os resultados e imprimir o progresso do treinamento. Se cada 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 da GPU que tenha 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 Braket SDK, ele fornece um argumento de palavra-chave conveniente. distribution Com a criação distribution="data_parallel" de empregos híbridos, o Amazon Braket SDK insere automaticamente os dois hiperparâmetros para você. Se você usa a API Amazon 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 pelas 8 GPUs na instância. Quando você define instanceCount mais de um, a carga de trabalho é distribuída entre as GPUs disponíveis em todas as instâncias. Ao usar várias instâncias, cada instância incorre em uma cobrança com base em quanto tempo você a usa. 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 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!