

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon EMR on EKS에서 Apache Spark용 RAPIDS 액셀러레이터 사용
<a name="tutorial-spark-rapids"></a>

Amazon EMR on EKS에서는 Apache Spark용 Nvidia RAPIDS 액셀러레이터 작업을 실행할 수 있습니다. 이 자습서에서는 EC2 그래픽 처리 장치(GPU) 인스턴스 유형에서 RAPIDS를 사용하여 Spark 작업을 실행하는 방법을 다룹니다. 자습서에서는 다음 버전을 사용합니다.
+ Amazon EMR on EKS 릴리스 버전 6.9.0 이상
+ Apache Spark 3.x

[Apache Spark용 Nvidia RAPIDS 액셀러레이터](https://docs.nvidia.com/spark-rapids/user-guide/latest/overview.html) 플러그인을 사용하면 Amazon EC2 GPU 인스턴스 유형으로 Spark를 가속화할 수 있습니다. 이러한 기술을 함께 사용하면 코드를 변경하지 않고도 데이터 과학 파이프라인을 가속화할 수 있습니다. 따라서 데이터 처리 및 모델 학습에 필요한 실행 시간도 줄어듭니다. 더 짧은 시간에 더 많은 작업을 수행하면 인프라 비용을 절감할 수 있습니다.

시작하기 전에 다음 리소스가 준비되었는지 확인합니다.
+ Amazon EMR on EKS 가상 클러스터
+ GPU 지원 노드 그룹이 있는 Amazon EKS 클러스터

Amazon EKS 가상 클러스터는 Amazon EKS 클러스터의 Kubernetes 네임스페이스에 등록된 핸들로, Amazon EMR on EKS에서 관리됩니다. 이 핸들을 사용하면 Amazon EMR에서 Kubernetes 네임스페이스를 실행 중인 작업의 대상으로 사용할 수 있습니다. 가상 클러스터를 설정하는 방법에 대한 자세한 내용은 이 안내서에서 [Amazon EMR on EKS 설정](setting-up.md) 섹션을 참조하세요.

GPU 인스턴스가 있는 노드 그룹을 포함하는 Amazon EKS 가상 클러스터를 구성해야 합니다. Nvidia 디바이스 플러그인으로 노드를 구성해야 합니다. 자세한 내용은 [관리형 노드 그룹](https://docs.aws.amazon.com/eks/latest/userguide/managed-node-groups.html)을 참조하세요.

GPU 지원 노드 그룹을 추가하도록 Amazon EKS 클러스터를 구성하려면 다음 절차를 수행합니다.

**GPU 지원 노드 그룹을 추가하는 방법**

1. 다음 [create-nodegroup](https://docs.aws.amazon.com/cli/latest/reference/eks/create-nodegroup.html) 명령을 사용하여 GPU 지원 노드 그룹을 생성합니다. Amazon EKS 클러스터에 대한 올바른 파라미터를 대체해야 합니다. Spark RAPIDS를 지원하는 인스턴스 유형(예: P4, P3, G5 또는 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. 클러스터의 각 노드에서 GPU 수를 생성하고 클러스터에서 GPU 지원 컨테이너를 실행하도록 클러스터에 Nvidia 디바이스 플러그인을 설치합니다. 다음 코드를 실행하여 플러그인을 설치합니다.

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

1. 클러스터의 각 노드에서 사용 가능한 GPU 수를 검증하려면 다음 명령을 실행합니다.

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

**Spark RAPIDS 작업을 실행하는 방법**

1. Amazon EMR on EKS 클러스터에 Spark RAPIDS 작업을 제출합니다. 다음 코드에서는 작업을 시작하는 명령 예제를 보여줍니다. 작업을 처음 실행할 때 이미지를 다운로드하고 노드에 캐싱하는 데 몇 분 정도 걸릴 수 있습니다.

   ```
   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. Spark RAPIDS 액셀러레이터가 활성화되었는지 검증하려면 Spark 드라이버 로그를 확인합니다. 이 로그는 CloudWatch 또는 `start-job-run` 명령을 실행할 때 지정한 S3 위치에 저장됩니다. 다음 예제는 일반적으로 로그 줄의 모양을 보여줍니다.

   ```
   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. GPU에서 실행될 작업을 확인하려면 다음 단계를 수행하여 추가 로깅을 활성화합니다. '`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}}"}}}'
   ```

   이전 명령은 GPU를 사용하는 작업의 예제입니다. 출력은 아래 예제와 비슷합니다. 출력을 이해하는 데 도움이 필요하면 이 키를 참조하세요.
   + `*` - GPU에서 작동하는 작업 표시
   + `!` - GPU에서 실행할 수 없는 작업 표시
   + `@` - GPU에서 작동하지만 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
   ```