Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Accélérez vos charges de travail hybrides grâce aux simulateurs intégrés de PennyLane
Voyons comment utiliser les simulateurs intégrés d'Amazon Braket Hybrid Jobs pour exécuter des charges de travail hybrides. PennyLane Le simulateur intégré basé sur le GPU de Pennylane utilise la bibliothèque Nvidia CuQuantum pour accélérerlightning.gpu
Le simulateur GPU intégré est préconfiguré dans tous les conteneurs de tâches Braket que les utilisateurs peuvent utiliser immédiatement. Dans cette page, nous vous montrons comment l'utiliser lightning.gpu
pour accélérer vos charges de travail hybrides.
Utilisation lightning.gpu
pour les charges de travail de l'algorithme d'optimisation approximative quantique
Prenons les exemples d'algorithmes d'optimisation approximative quantique (QAOA) de ce carnet.device
argument doit être une chaîne de la forme :"local:<provider>/<simulator_name>"
. Par exemple, vous devez définir "local:pennylane/lightning.gpu"
pourlightning.gpu
. La chaîne de périphérique que vous donnez au Job hybride lorsque vous le lancez est transmise au job en tant que variable d'environnement"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)
Dans cette page, comparons les deux simulateurs vectoriels PennyLane d'état intégrés lightning.qubit
(basés sur le processeur) et lightning.gpu
(basés sur le GPU). Vous devrez fournir aux simulateurs des décompositions de portes personnalisées afin de calculer différents dégradés.
Vous êtes maintenant prêt à préparer le script de lancement de tâches hybrides. Vous allez exécuter l'algorithme QAOA à l'aide de deux types d'instances : m5.2xlarge
et. p3.2xlarge
Le type d'm5.2xlarge
instance est comparable à celui d'un ordinateur portable de développeur standard. p3.2xlarge
Il s'agit d'une instance de calcul accéléré dotée d'un seul GPU NVIDIA Volta avec 16 Go de mémoire.
Il en sera de même hyperparameters
pour tous vos emplois hybrides. Pour essayer différentes instances et simulateurs, il vous suffit de modifier deux lignes comme suit.
# 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')
Note
Si vous spécifiez le instance_config
comme utilisant une instance basée sur le GPU, mais que vous choisissez le device
simulateur intégré basé sur le processeur (lightning.qubit
), le GPU ne sera pas utilisé. Assurez-vous d'utiliser le simulateur intégré basé sur le GPU si vous souhaitez cibler le GPU !
Tout d'abord, vous pouvez créer deux tâches hybrides et résoudre Max-Cut avec QAOA sur un graphique à 18 sommets. Cela se traduit par un circuit de 18 qubits, relativement petit et pouvant être exécuté rapidement sur votre ordinateur portable ou sur l'instance. 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, )
Le temps d'itération moyen pour l'm5.2xlarge
instance est d'environ 25 secondes, tandis que pour l'p3.2xlarge
instance, il est d'environ 12 secondes. Pour ce flux de travail à 18 qubits, l'instance GPU nous permet d'accélérer deux fois plus vite. Si vous consultez la page de tarificationm5.2xlarge
instance est de 0,00768 USD, tandis que pour l'instance, il est de 0,06375 p3.2xlarge
USD. Exécuter 5 itérations au total, comme vous l'avez fait ici, coûterait 0,016$ avec l'instance du processeur ou 0,06375$ avec l'instance du GPU, ce qui est très peu coûteux !
Maintenant, compliquons le problème et essayons de résoudre un problème Max-Cut sur un graphe à 24 sommets, ce qui se traduira par 24 qubits. Réexécutez les tâches hybrides sur les deux mêmes instances et comparez les coûts.
Note
Vous verrez que le temps d'exécution de cette tâche hybride sur l'instance du processeur peut être d'environ cinq heures !
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, )
Le temps d'itération moyen pour l'm5.2xlarge
instance est d'environ une heure, tandis que pour l'p3.2xlarge
instance, il est d'environ deux minutes. Pour ce problème plus important, l'instance GPU est un ordre de grandeur plus rapide ! Pour bénéficier de cette accélération, il vous suffisait de modifier deux lignes de code, en remplaçant le type d'instance et le simulateur local utilisé. L'exécution pendant 5 itérations au total, comme cela a été fait ici, coûterait environ 2,27072$ en utilisant l'instance CPU ou environ 0,775625$ en utilisant l'instance GPU. L'utilisation du processeur est non seulement plus coûteuse, mais elle prend également plus de temps à fonctionner. L'accélération de ce flux de travail à l'aide d'une instance GPU disponible sur AWS, à l'aide PennyLane du simulateur intégré soutenu par NVIDIA CuQuantum, vous permet d'exécuter des flux de travail avec un nombre de qubits intermédiaire (entre 20 et 30) à moindre coût total et en moins de temps. Cela signifie que vous pouvez expérimenter l'informatique quantique même pour des problèmes trop importants pour être exécutés rapidement sur votre ordinateur portable ou sur une instance de taille similaire.
Apprentissage automatique quantique et parallélisme des données
Si votre type de charge de travail est l'apprentissage automatique quantique (QML) qui s'entraîne sur des ensembles de données, vous pouvez encore accélérer votre charge de travail grâce au parallélisme des données. Dans QML, le modèle contient un ou plusieurs circuits quantiques. Le modèle peut également contenir ou non des réseaux neuronaux classiques. Lors de l'entraînement du modèle avec le jeu de données, les paramètres du modèle sont mis à jour afin de minimiser la fonction de perte. Une fonction de perte est généralement définie pour un seul point de données, et la perte totale est définie pour la perte moyenne sur l'ensemble de données. En QML, les pertes sont généralement calculées en série avant d'être moyennées par rapport à la perte totale pour les calculs de gradient. Cette procédure prend beaucoup de temps, en particulier lorsqu'il existe des centaines de points de données.
Comme la perte d'un point de données ne dépend pas des autres points de données, les pertes peuvent être évaluées en parallèle ! Les pertes et les gradients associés à différents points de données peuvent être évalués en même temps. C'est ce que l'on appelle le parallélisme des données. Grâce à SageMaker sa bibliothèque de données parallèles distribuées, Amazon Braket Hybrid Jobs vous permet de tirer plus facilement parti du parallélisme des données pour accélérer votre formation.
Considérez la charge de travail QML suivante pour le parallélisme des données, qui utilise le jeu de données Sonarlightning.gpu
pour améliorer les performances par rapport aux simulateurs intégrés basés sur le processeur.
Pour créer une tâche hybride, vous pouvez appeler AwsQuantumJob.create
et spécifier le script d'algorithme, le périphérique et d'autres configurations via ses arguments de mots clés.
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, ... )
Pour utiliser le parallélisme des données, vous devez modifier quelques lignes de code dans le script d'algorithme de la bibliothèque SageMaker distribuée afin de paralléliser correctement l'apprentissage. Tout d'abord, vous importez le smdistributed
package qui effectue le plus gros du travail pour répartir vos charges de travail sur plusieurs GPU et plusieurs instances. Ce package est préconfiguré dans le Braket PyTorch et TensorFlow les conteneurs. Le dist
module indique à notre script d'algorithme le nombre total de GPU pour l'entraînement (world_size
) ainsi que la fin rank
local_rank
d'un cœur de GPU. rank
est l'indice absolu d'un GPU pour toutes les instances, tandis local_rank
que l'indice d'un GPU au sein d'une instance. Par exemple, si quatre instances disposent chacune de huit GPU alloués à l'entraînement, les rank
valeurs sont comprises entre 0 et 31 et local_rank
entre 0 et 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)
Ensuite, vous définissez un DistributedSampler
en fonction du world_size
rank
et puis vous le transmettez au chargeur de données. Cet échantillonneur évite aux GPU d'accéder à la même tranche d'un ensemble de données.
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, )
Ensuite, vous utilisez la DistributedDataParallel
classe pour activer le parallélisme des données.
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"])
Les modifications ci-dessus sont nécessaires pour utiliser le parallélisme des données. Dans QML, vous souhaitez souvent enregistrer les résultats et imprimer la progression de l'entraînement. Si chaque GPU exécute la commande d'enregistrement et d'impression, le journal sera inondé d'informations répétées et les résultats se remplaceront mutuellement. Pour éviter cela, vous ne pouvez enregistrer et imprimer qu'à partir du GPU dont la valeur est 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})
Amazon Braket Hybrid Jobs prend en charge les types d'ml.p3.16xlarge
instances pour la bibliothèque parallèle de données SageMaker distribuées. Vous configurez le type d'instance via l'InstanceConfig
argument dans Hybrid Jobs. Pour que la bibliothèque de données parallèles SageMaker distribuées sache que le parallélisme des données est activé, vous devez ajouter deux hyperparamètres supplémentaires, en "sagemaker_distributed_dataparallel_enabled"
"sagemaker_instance_type"
définissant "true"
et en fonction du type d'instance que vous utilisez. Ces deux hyperparamètres sont utilisés par le smdistributed
package. Votre script d'algorithme n'a pas besoin de les utiliser explicitement. Dans le SDK Amazon Braket, il fournit un argument de mot clé pratique. distribution
distribution="data_parallel"
Dans le cadre de la création de tâches hybrides, le SDK Amazon Braket insère automatiquement les deux hyperparamètres pour vous. Si vous utilisez l'API Amazon Braket, vous devez inclure ces deux hyperparamètres.
Une fois le parallélisme des instances et des données configuré, vous pouvez désormais soumettre votre tâche hybride. Il y a 8 GPU dans une ml.p3.16xlarge
instance. Lorsque vous définissezinstanceCount=1
, la charge de travail est répartie sur les 8 GPU de l'instance. Lorsque vous définissez une instanceCount
valeur supérieure à un, la charge de travail est répartie sur les GPU disponibles dans toutes les instances. Lorsque vous utilisez plusieurs instances, chaque instance est facturée en fonction de la durée pendant laquelle vous l'utilisez. Par exemple, lorsque vous utilisez quatre instances, le temps facturable est quatre fois supérieur au temps d'exécution par instance, car quatre instances exécutent vos charges de travail en même temps.
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", ... )
Note
Dans la création de tâches hybrides ci-dessus, train_dp.py
se trouve le script d'algorithme modifié pour utiliser le parallélisme des données. N'oubliez pas que le parallélisme des données ne fonctionne correctement que lorsque vous modifiez votre script d'algorithme conformément à la section ci-dessus. Si l'option de parallélisme des données est activée sans qu'un script d'algorithme soit correctement modifié, la tâche hybride peut générer des erreurs ou chaque GPU peut traiter à plusieurs reprises la même tranche de données, ce qui est inefficace.
Comparons le temps d'exécution et le coût dans un exemple où nous entraînons un modèle avec un circuit quantique de 26 qubits pour le problème de classification binaire mentionné ci-dessus. L'ml.p3.16xlarge
instance utilisée dans cet exemple coûte 0,4692 USD par minute. Sans le parallélisme des données, le simulateur met environ 45 minutes à entraîner le modèle pour une époque (c'est-à-dire plus de 208 points de données) et cela coûte environ 20$. Avec le parallélisme des données entre 1 instance et 4 instances, cela ne prend que 6 minutes et 1,5 minute respectivement, ce qui se traduit par environ 2,8$ pour les deux. En utilisant le parallélisme des données sur 4 instances, non seulement vous multipliez par 30 le temps d'exécution, mais vous réduisez également les coûts d'un ordre de grandeur !