

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Ejecute cargas de trabajo híbridas con simuladores integrados PennyLane
<a name="pennylane-embedded-simulators"></a>

Veamos cómo puede utilizar los simuladores integrados de PennyLane Amazon Braket Hybrid Jobs para ejecutar cargas de trabajo híbridas. El simulador GPU-based integrado de Pennylane utiliza la biblioteca [CuQuantum de Nvidia para acelerar las simulaciones de circuitos](https://developer.nvidia.com/cuquantum-sdk). `lightning.gpu` El simulador de GPU integrado viene preconfigurado en todos los [contenedores de trabajos](https://github.com/amazon-braket/amazon-braket-containers) de Braket, que los usuarios pueden utilizar de forma inmediata. En esta página, le mostramos cómo usar `lightning.gpu` para acelerar las cargas de trabajo híbridas.

## Uso de `lightning.gpu para cargas de trabajo de AOA`
<a name="lightning-gpu-qaoa"></a>

Considere los ejemplos del algoritmo de optimización cuántica aproximada (QAOA) de este [cuaderno](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/hybrid_jobs/2_Using_PennyLane_with_Braket_Hybrid_Jobs). Para seleccionar un simulador integrado, debe especificar que el argumento `device` sea una cadena con la forma: `"local:<provider>/<simulator_name>"`. Por ejemplo, configuraría `"local:pennylane/lightning.gpu"` para `lightning.gpu`. La cadena de dispositivo que proporciona al trabajo híbrido al iniciarlo se pasa al trabajo como el `"AMZN_BRAKET_DEVICE_ARN"` de la variable de entorno.

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

En esta página, compare los dos simuladores vectoriales de PennyLane estado integrados (cuál es) y `lightning.qubit` (cuál es CPU-based). `lightning.gpu` GPU-based Proporcione a los simuladores descomposiciones de puertas personalizadas para calcular varios gradientes.

Ahora ya puede preparar el script de lanzamiento del trabajo híbrido. Ejecute el algoritmo QAOA mediante dos tipos de instancias: `ml.m5.2xlarge` y `ml.g4dn.xlarge`. El tipo de instancia `ml.m5.2xlarge` es equiparable al de un portátil de desarrollador estándar. `ml.g4dn.xlarge`Se trata de una instancia de computación acelerada que tiene una sola GPU NVIDIA T4 con 16 GB de memoria.

Para ejecutar la GPU, primero debemos especificar una imagen compatible y la instancia correcta (que por defecto es una `ml.m5.2xlarge` instancia).

```
from braket.aws import AwsSession
from braket.jobs.image_uris import Framework, retrieve_image

image_uri = retrieve_image(Framework.PL_PYTORCH, AwsSession().region)
instance_config = InstanceConfig(instanceType="ml.g4dn.xlarge")
```

A continuación, debemos introducirlos en el decorador de tareas híbridas, junto con los parámetros actualizados del dispositivo, tanto en el sistema como en los argumentos de los trabajos híbridos.

```
@hybrid_job(
        device="local:pennylane/lightning.gpu",
        input_data=input_file_path,
        image_uri=image_uri,
        instance_config=instance_config)
def run_qaoa_hybrid_job_gpu(p=1, steps=10):
    params = np.random.rand(2, p)

    braket_task_tracker = Tracker()

    graph = nx.read_adjlist(input_file_path, nodetype=int)
    wires = list(graph.nodes)
    cost_h, _mixer_h = qaoa.maxcut(graph)

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

**nota**  
Si especificas el `instance_config` as mediante una GPU-based instancia, pero eliges `device` que sea el CPU-based simulador integrado (`lightning.qubit`), no se utilizará la GPU. ¡Asegúrate de usar el GPU-based simulador integrado si deseas apuntar a la GPU\!

El tiempo medio de iteración de la `m5.2xlarge` instancia es de unos 73 segundos, mientras que el de la `ml.g4dn.xlarge` instancia es de unos 0,6 segundos. Para este flujo de trabajo de 21 qubits, la instancia de GPU nos proporciona una aceleración de 100 veces. Si consulta la [página de precios](https://aws.amazon.com/braket/pricing/) de Amazon Braket Hybrid Jobs, verá que el coste por minuto de una `m5.2xlarge` instancia es de 0,00768$, mientras que para la `ml.g4dn.xlarge` instancia es de 0,01227$. En este caso, es más rápido y económico ejecutarlo en la instancia de GPU.

## Machine learning cuántico y paralelismo de datos
<a name="quantumML-data-parallelism"></a>

Si su tipo de carga de trabajo es el machine learning cuántico (QML) que se entrena con conjuntos de datos, puede acelerar aún más su carga de trabajo utilizando el paralelismo de datos. En QML, el modelo contiene uno o más circuitos cuánticos. El modelo puede o no contener también redes neuronales clásicas. Al entrenar el modelo con el conjunto de datos, los parámetros del modelo se actualizan para minimizar la función de pérdida. Por lo general, se define una función de pérdida para un único punto de datos y la pérdida total para la pérdida media de todo el conjunto de datos. En QML, las pérdidas generalmente se calculan en serie antes de promediar la pérdida total para los cómputos de gradientes. Este procedimiento lleva mucho tiempo, especialmente cuando hay cientos de puntos de datos.

Como la pérdida de un punto de datos no depende de otros puntos de datos, las pérdidas se pueden evaluar en paralelo. Las pérdidas y los gradientes asociados a diferentes puntos de datos se pueden evaluar al mismo tiempo. Esto se conoce como paralelismo de datos. Con SageMaker la biblioteca paralela de datos distribuida, Amazon Braket Hybrid Jobs le facilita el uso del paralelismo de datos para acelerar su entrenamiento.

Considere la siguiente carga de trabajo de QML para el paralelismo de datos, que utiliza el [conjunto de datos Sonar](https://archive.ics.uci.edu/dataset/151/connectionist+bench+sonar+mines+vs+rocks) del conocido repositorio de UCI como ejemplo para la clasificación binaria. El conjunto de datos de Sonar tiene 208 puntos de datos, cada uno con 60 características que se recopilan a partir de señales de Sonar que rebotan en los materiales. Cada punto de datos se etiqueta con una «M» para las minas o con una «R» para las rocas. Nuestro modelo QML consta de una capa de entrada, un circuito cuántico como capa oculta y una capa de salida. Las capas de entrada y salida son redes neuronales clásicas implementadas en. PyTorch El circuito cuántico se integra con las redes PyTorch neuronales mediante PennyLane el módulo qml.qnn. Consulte nuestros [cuadernos de ejemplo](https://github.com/aws/amazon-braket-examples) para obtener más detalles sobre la carga de trabajo. Al igual que en el ejemplo anterior de QAOA, puedes aprovechar la potencia de la GPU mediante el uso de simuladores integrados para mejorar el rendimiento en comparación con GPU-based los simuladores integrados. PennyLane `lightning.gpu` CPU-based

Para crear un trabajo híbrido, puede llamar a `AwsQuantumJob.create` y especificar el script del algoritmo, el dispositivo y otras configuraciones a través de sus argumentos de palabra clave.

```
instance_config = InstanceConfig(instanceType='ml.g4dn.xlarge')

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 utilizar el paralelismo de datos, es necesario modificar algunas líneas de código en el script del algoritmo para que la biblioteca SageMaker distribuida paralelice correctamente el entrenamiento. En primer lugar, debe importar el paquete de `smdistributed` que se encarga de la mayor parte del trabajo pesado de distribuir las cargas de trabajo entre varias GPU y varias instancias. Este paquete está preconfigurado en Braket y en los contenedores. PyTorch TensorFlow El módulo `dist` indica a nuestro script de algoritmo cuál es el número total de GPU para el entrenamiento (`world_size`), así como el `rank` y `local_rank` de un núcleo de GPU. `rank` es el índice absoluto de una GPU en todas las instancias, mientras que `local_rank` es el índice de una GPU dentro de una instancia. Por ejemplo, si hay cuatro instancias, cada una con ocho GPU asignadas para el entrenamiento, los rangos de `rank` van de 0 a 31 y los rangos de `local_rank` 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)
```

A continuación, se define un `DistributedSampler` según el `world_size` y `rank` y, después, se pasa al cargador de datos. Este muestreador evita que las GPU accedan al mismo segmento de un conjunto de datos.

```
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,
)
```

A continuación, use la clase `DistributedDataParallel` para habilitar el paralelismo de datos.

```
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"])
```

Los cambios anteriores son los que necesita para usar el paralelismo de datos. Generalmente, en QML es conveniente guardar los resultados e imprimir el progreso del entrenamiento. Si cada GPU ejecuta el comando de guardar e imprimir, el registro se saturará con información repetida y los resultados se sobrescribirán entre sí. Para evitarlo, solo puede guardar e imprimir desde la GPU que tiene `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 admite tipos de `ml.g4dn.12xlarge` instancias para la biblioteca paralela de datos SageMaker distribuidos. El tipo de instancia se configura mediante el argumento `InstanceConfig` en los trabajos híbridos. Para que la biblioteca paralela de datos SageMaker distribuidos sepa que el paralelismo de datos está habilitado, debe agregar dos hiperparámetros adicionales: configurar `"true"` y `"sagemaker_distributed_dataparallel_enabled"` `"sagemaker_instance_type"` configurar el tipo de instancia que está utilizando. El paquete de `smdistributed` utiliza estos dos hiperparámetros. El script de algoritmo no necesita usarlos de forma explícita. En el SDK de Amazon Braket, proporciona un práctico argumento de palabra clave `distribution`. Con el `distribution="data_parallel"` en la creación de trabajos híbridos, el SDK de Amazon Braket inserta automáticamente los dos hiperparámetros por usted. Si utiliza la API de Amazon Braket, debe incluir estos dos hiperparámetros.

Una vez configurados el paralelismo de datos y la instancia, ya puede enviar su trabajo híbrido. Hay 4 GPU en una instancia. `ml.g4dn.12xlarge` Cuando configura `instanceCount=1`, la carga de trabajo se distribuye entre las 8 GPU en la instancia. Si configura `instanceCount` superior a uno, la carga de trabajo se distribuye entre las GPU disponibles en todas las instancias. Al usar varias instancias, cada instancia conlleva un cargo en función del tiempo que la utilice. Por ejemplo, cuando utiliza cuatro instancias, el tiempo facturable es cuatro veces el tiempo de ejecución por instancia, ya que hay cuatro instancias ejecutando sus cargas de trabajo al mismo tiempo.

```
instance_config = InstanceConfig(instanceType='ml.g4dn.12xlarge',
                                 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**  
En la creación del trabajo híbrido anterior, `train_dp.py` es el script del algoritmo modificado para utilizar el paralelismo de datos. Tenga en cuenta que el paralelismo de datos solo funciona correctamente cuando modifica el script de algoritmo según lo indicado en la sección anterior. Si se habilita la opción de paralelismo de datos sin un script de algoritmo modificado correctamente, el trabajo híbrido puede generar errores, o cada GPU puede procesar repetidamente la misma porción de datos, lo cual es ineficiente.

Si se utiliza correctamente, el uso de varias instancias puede suponer una reducción de varios órdenes de magnitud tanto en tiempo como en costes. Consulte el [cuaderno de ejemplo para obtener más información](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/hybrid_jobs/5_Parallelize_training_for_QML/Parallelize_training_for_QML.ipynb).