Uso del acelerador RAPIDS para Apache Spark con Amazon EMR en EKS
Con Amazon EMR en EKS, puede ejecutar trabajos para el acelerador RAPIDS de Nvidia para Apache Spark. Este tutorial explica cómo ejecutar trabajos de Spark con RAPIDS en tipos de instancias de unidades de procesamiento gráfico (GPU) de EC2. El tutorial utiliza las siguientes versiones:
-
Versión de lanzamiento de Amazon EMR en EKS 6.9.0 y versiones posteriores
-
Apache Spark 3.x
Puede acelerar Spark con los tipos de instancias de GPU de Amazon EC2 mediante el complemento Acelerador RAPIDS para Apache Spark
Antes de empezar, asegúrese de que disponga de los siguientes recursos.
-
Clúster virtual de Amazon EMR en EKS
-
Clúster de Amazon EKS con un grupo de nodos habilitados para GPU
Un clúster virtual de Amazon EKS es un identificador registrado para el espacio de nombres de Kubernetes en un clúster de Amazon EKS y lo administra Amazon EMR en EKS. El identificador permite a Amazon EMR utilizar el espacio de nombres de Kubernetes como destino para ejecutar trabajos. Para obtener más información sobre cómo configurar un clúster virtual, consulte Configuración de Amazon EMR en EKS en esta guía.
Debe configurar el clúster virtual de Amazon EKS con un grupo de nodos que tenga instancias de GPU. Debe configurar los nodos con un complemento de dispositivo NVIDIA. Para obtener más información, consulte Grupos de nodos administrados.
Para configurar su clúster de Amazon EKS para agregar grupos de nodos habilitados para GPU, siga este procedimiento:
Para agregar grupos de nodos habilitados para GPU
-
Cree un grupo de nodos habilitado para GPU con el comando create-nodegroup. Asegúrese de sustituir los parámetros correctos para su clúster de Amazon EKS. Utilice un tipo de instancia que sea compatible con RAPIDS para Spark, como P4, P3, G5 o G4dn.
aws eks create-nodegroup \ --cluster-name
EKS_CLUSTER_NAME
\ --nodegroup-nameNODEGROUP_NAME
\ --scaling-config minSize=0,maxSize=5,desiredSize=2CHOOSE_APPROPRIATELY
\ --ami-type AL2_x86_64_GPU \ --node-roleNODE_ROLE
\ --subnetsSUBNETS_SPACE_DELIMITED
\ --remote-access ec2SshKey=SSH_KEY
\ --instance-typesGPU_INSTANCE_TYPE
\ --disk-sizeDISK_SIZE
\ --regionAWS_REGION
-
Instale el complemento de dispositivo Nvidia en su clúster para emitir la cantidad de GPU en cada nodo de su clúster y ejecutar contenedores habilitados para GPU en su clúster. Ejecute el siguiente comando para instalar el complemento:
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml
-
Para validar cuántas GPU hay disponibles en cada nodo del clúster, ejecute el siguiente comando:
kubectl get nodes "-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"
Para ejecutar un trabajo de RAPIDS para Spark
-
Envíe un trabajo de RAPIDS para Spark a su clúster de Amazon EMR en EKS. En el siguiente código, se muestra un ejemplo de comando para iniciar el trabajo. La primera vez que ejecute el trabajo, es posible que tarde unos minutos en descargar la imagen y almacenarla en caché en el nodo.
aws emr-containers start-job-run \ --virtual-cluster-id
VIRTUAL_CLUSTER_ID
\ --execution-role-arnJOB_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
"}}}' -
Para validar que el acelerador de RAPIDS para Spark esté activado, consulte los registros de los controladores de Spark. Estos registros se almacenan en CloudWatch o en la ubicación S3 que especifique al ejecutar el comando
start-job-run
. El siguiente ejemplo muestra en general cómo se ven las líneas de registro: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.
-
Para ver las operaciones que se ejecutarán en una GPU, siga estos pasos para habilitar el registro adicional. Tenga en cuenta la configuración “
spark.rapids.sql.explain : ALL
”.aws emr-containers start-job-run \ --virtual-cluster-id
VIRTUAL_CLUSTER_ID
\ --execution-role-arnJOB_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
"}}}'El comando anterior es un ejemplo de un trabajo que utiliza la GPU. Su resultado se parecería al del ejemplo siguiente. Consulte esta clave como ayuda para entender el resultado:
-
*
: marca una operación que funciona en una GPU -
!
: marca una operación que no se puede ejecutar en una GPU -
@
: marca una operación que funciona en una GPU, pero que no se puede ejecutar porque está incluida en un plan que no se puede ejecutar en una 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
-