

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á.

# Uso do acelerador RAPIDS para Apache Spark com o Amazon EMR no EKS
<a name="tutorial-spark-rapids"></a>

Com o Amazon EMR no EKS, você pode executar trabalhos para o acelerador RAPIDS da Nvidia para Apache Spark. Este tutorial aborda como executar trabalhos do Spark usando o RAPIDS em tipos de instância de unidade de processamento gráfico (GPU) do EC2. O tutorial usa as seguintes versões:
+ Amazon EMR no EKS na versão de liberação 6.9.0 e posteriores
+ Apache Spark 3.x

Você pode acelerar o Spark com os tipos de instância de GPU do Amazon EC2 usando o plug-in do [acelerador RAPIDS da Nvidia para Apache Spark](https://docs.nvidia.com/spark-rapids/user-guide/latest/overview.html). Ao usar essas tecnologias em conjunto, você acelera os pipelines de ciência de dados sem a necessidade de realizar alterações no código. Isso reduz o tempo de execução necessário para o processamento de dados e para o treinamento de modelos. Ao fazer mais em menos tempo, você gasta menos com o custo da infraestrutura.

Antes de começar, certifique-se de ter os recursos apresentados a seguir. 
+ Cluster virtual do Amazon EMR no EKS
+ Cluster do Amazon EKS com um grupo de nós habilitado para GPU

Um cluster virtual do Amazon EKS corresponde a um manipulador registrado para o namespace do Kubernetes em um cluster do Amazon EKS e é gerenciado pelo Amazon EMR no EKS. O manipulador permite que o Amazon EMR use o namespace do Kubernetes como destino para a execução de trabalhos. Para obter mais informações sobre como configurar um cluster virtual, consulte [Configuração do Amazon EMR no EKS](setting-up.md) neste guia.

Você deve configurar o cluster virtual do Amazon EKS com um grupo de nós que tenha instâncias de GPU. Você deve configurar os nós com um plug-in para dispositivos da Nvidia. Consulte [Grupos de nós gerenciados](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html) para saber mais.

Para configurar o cluster do Amazon EKS para adicionar grupos de nós habilitados para GPU, execute o seguinte procedimento:

**Adicionar grupos de nós habilitados para GPU**

1. Crie um grupo de nós habilitado para GPU com o comando [create-nodegroup](https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html) apresentado a seguir. Certifique-se de realizar a substituição com os parâmetros corretos para o cluster do Amazon EKS. Use um tipo de instância compatível com RAPIDS para Spark, como P4, P3, G5 ou G4dn. 

   ```
   aws eks create-nodegroup \
    --cluster-name {{EKS_CLUSTER_NAME}} \
    --nodegroup-name {{NODEGROUP_NAME}} \
    --scaling-config minSize=0,maxSize=5,desiredSize=2 {{CHOOSE_APPROPRIATELY}} \
    --ami-type AL2_x86_64_GPU \
    --node-role {{NODE_ROLE}} \
    --subnets {{SUBNETS_SPACE_DELIMITED}}  \
    --remote-access ec2SshKey= {{SSH_KEY}} \
    --instance-types {{GPU_INSTANCE_TYPE}} \
    --disk-size {{DISK_SIZE}} \
    --region {{AWS_REGION}}
   ```

1. Instale o plug-in do dispositivo Nvidia em seu cluster para emitir o número de GPUs em cada nó do seu cluster e para executar contêineres habilitados para GPU em seu cluster. Execute o seguinte código para instalar o plug-in:

   ```
   kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml
   ```

1. Para validar quantos GPUs estão disponíveis em cada nó do seu cluster, execute o seguinte comando:

   ```
   kubectl get nodes  "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"
   ```

**Executar um trabalho do RAPIDS para Spark**

1. Envie um trabalho do RAPIDS para Spark ao cluster do Amazon EMR no EKS. O código a seguir apresenta um exemplo de comando para iniciar o trabalho. Na primeira vez em que você executar o trabalho, poderá demorar alguns minutos para fazer download da imagem e armazená-la em cache no nó.

   ```
   aws emr-containers start-job-run \
   --virtual-cluster-id {{VIRTUAL_CLUSTER_ID}} \
   --execution-role-arn {{JOB_EXECUTION_ROLE}} \
   --release-label emr-6.9.0-spark-rapids-latest \
   --job-driver '{"sparkSubmitJobDriver": {"entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar","entryPointArguments":  ["10000"], "sparkSubmitParameters":"--class org.apache.spark.examples.SparkPi "}}' \
   ---configuration-overrides '{"applicationConfiguration": [{"classification": "spark-defaults","properties": {"spark.executor.instances": "2","spark.executor.memory": "2G"}}],"monitoringConfiguration": {"cloudWatchMonitoringConfiguration": {"logGroupName": "{{LOG_GROUP _NAME}}"},"s3MonitoringConfiguration": {"logUri": "{{LOG_GROUP_STREAM}}"}}}'
   ```

1. Para validar se o acelerador RAPIDS para Spark está habilitado, verifique os logs do driver do Spark. Esses registros são armazenados no CloudWatch local do S3 que você especifica ao executar o `start-job-run` comando. O seguinte exemplo apresenta como geralmente é a aparência das linhas de log:

   ```
   22/11/15 00:12:44 INFO RapidsPluginUtils: RAPIDS Accelerator build: {version=22.08.0-amzn-0, user=release, url=, date=2022-11-03T03:32:45Z, revision=, cudf_version=22.08.0, branch=}
   22/11/15 00:12:44 INFO RapidsPluginUtils: RAPIDS Accelerator JNI build: {version=22.08.0, user=, url=https://github.com/NVIDIA/spark-rapids-jni.git, date=2022-08-18T04:14:34Z, revision=a1b23cd_sample, branch=HEAD}
   22/11/15 00:12:44 INFO RapidsPluginUtils: cudf build: {version=22.08.0, user=, url=https://github.com/rapidsai/cudf.git, date=2022-08-18T04:14:34Z, revision=a1b23ce_sample, branch=HEAD}
   22/11/15 00:12:44 WARN RapidsPluginUtils: RAPIDS Accelerator 22.08.0-amzn-0 using cudf 22.08.0.
   22/11/15 00:12:44 WARN RapidsPluginUtils: spark.rapids.sql.multiThreadedRead.numThreads is set to 20.
   22/11/15 00:12:44 WARN RapidsPluginUtils: RAPIDS Accelerator is enabled, to disable GPU support set `spark.rapids.sql.enabled` to false.
   22/11/15 00:12:44 WARN RapidsPluginUtils: spark.rapids.sql.explain is set to `NOT_ON_GPU`. Set it to 'NONE' to suppress the diagnostics logging about the query placement on the GPU.
   ```

1. Para visualizar as operações que serão executadas em uma GPU, execute as etapas apresentadas a seguir para ativar o registro em log adicional. Observe a configuração “`spark.rapids.sql.explain : ALL`”.

   ```
   aws emr-containers start-job-run \
   --virtual-cluster-id {{VIRTUAL_CLUSTER_ID}} \
   --execution-role-arn {{JOB_EXECUTION_ROLE}} \
   --release-label emr-6.9.0-spark-rapids-latest \
   --job-driver '{"sparkSubmitJobDriver": {"entryPoint": "local:///usr/lib/spark/examples/jars/spark-examples.jar","entryPointArguments":  ["10000"], "sparkSubmitParameters":"--class org.apache.spark.examples.SparkPi "}}' \
   ---configuration-overrides '{"applicationConfiguration": [{"classification": "spark-defaults","properties": {"spark.rapids.sql.explain":"ALL","spark.executor.instances": "2","spark.executor.memory": "2G"}}],"monitoringConfiguration": {"cloudWatchMonitoringConfiguration": {"logGroupName": "{{LOG_GROUP_NAME}}"},"s3MonitoringConfiguration": {"logUri": "{{LOG_GROUP_STREAM}}"}}}'
   ```

   O comando anterior é um exemplo de trabalho que usa a GPU. Sua saída seria semelhante ao exemplo abaixo. Consulte esta legenda para obter ajuda para compreender a saída:
   + `*`: marca uma operação que funciona em uma GPU.
   + `!`: marca uma operação que não pode ser executada em uma GPU.
   + `@`: marca uma operação que funciona em uma GPU, mas não será executada porque está em um plano que não pode ser executado em uma GPU.

   ```
    22/11/15 01:22:58 INFO GpuOverrides: Plan conversion to the GPU took 118.64 ms
    22/11/15 01:22:58 INFO GpuOverrides: Plan conversion to the GPU took 4.20 ms
    22/11/15 01:22:58 INFO GpuOverrides: GPU plan transition optimization took 8.37 ms
    22/11/15 01:22:59 WARN GpuOverrides:
       *Exec <ProjectExec> will run on GPU
         *Expression <Alias> substring(cast(date#149 as string), 0, 7) AS month#310 will run on GPU
           *Expression <Substring> substring(cast(date#149 as string), 0, 7) will run on GPU
             *Expression <Cast> cast(date#149 as string) will run on GPU
         *Exec <SortExec> will run on GPU
           *Expression <SortOrder> date#149 ASC NULLS FIRST will run on GPU
           *Exec <ShuffleExchangeExec> will run on GPU
             *Partitioning <RangePartitioning> will run on GPU
               *Expression <SortOrder> date#149 ASC NULLS FIRST will run on GPU
             *Exec <UnionExec> will run on GPU
               !Exec <ProjectExec> cannot run on GPU because not all expressions can be replaced
                 @Expression <AttributeReference> customerID#0 could run on GPU
                 @Expression <Alias> Charge AS kind#126 could run on GPU
                   @Expression <Literal> Charge could run on GPU
                 @Expression <AttributeReference> value#129 could run on GPU
                 @Expression <Alias> add_months(2022-11-15, cast(-(cast(_we0#142 as bigint) + last_month#128L) as int)) AS date#149 could run on GPU
                   ! <AddMonths> add_months(2022-11-15, cast(-(cast(_we0#142 as bigint) + last_month#128L) as int)) cannot run on GPU because GPU does not currently support the operator class org.apache.spark.sql.catalyst.expressions.AddMonths
                     @Expression <Literal> 2022-11-15 could run on GPU
                     @Expression <Cast> cast(-(cast(_we0#142 as bigint) + last_month#128L) as int) could run on GPU
                       @Expression <UnaryMinus> -(cast(_we0#142 as bigint) + last_month#128L) could run on GPU
                         @Expression <Add> (cast(_we0#142 as bigint) + last_month#128L) could run on GPU
                           @Expression <Cast> cast(_we0#142 as bigint) could run on GPU
                             @Expression <AttributeReference> _we0#142 could run on GPU
                           @Expression <AttributeReference> last_month#128L could run on GPU
   ```