AWS 기술 블로그

Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 2 – AWS ParallelCluster

서론

“Amazon EC2 가속 컴퓨팅 인스턴스 활용하기” 블로그 시리즈는 Amazon EC2의 가속 컴퓨팅 인스턴스와 AWS에서 제공되는 다양한 리소스를 이용하여, 멀티 노드 가속 컴퓨팅 환경을 쉽게 구축할 수 있는 방법에 대해서 알아 봅니다. 블로그는 아래와 같이 3개의 시리즈로 구성이 되어 있으며, “Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 1 – AWS Deep Learning AMI (DLAMI)”에서 DLAMI를 사용하여 가속 컴퓨팅 환경을, 쉽고 빠르게 구축할 수 있는 방법에 대해서 알아 보았습니다.

  1. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 1 – AWS Deep Learning AMI (DLAMI)
  2. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 2 – AWS ParallelCluster
  3. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 3 – Amazon Elastic Kubernetes Service (EKS) 기반의 GPU 클러스터

파트 2에서는 가속 컴퓨팅 클러스터를 쉽게 배포하고 관리할 수 있게 해 주는 오픈 소스 클러스터 관리 도구인 AWS ParallelCluster에 대해서 알아 볼 것입니다. ParallelCluster는 간단한 그래픽 사용자 인터페이스(GUI) 또는 텍스트 파일을 사용해 자동화되고 안전한 방식으로 HPC 애플리케이션에 필요한 리소스를 모델링하고 프로비저닝합니다. 또한 여러 인스턴스 유형과 작업 제출 대기열, 그리고 AWS BatchSlurm과 같은 작업 스케줄러를 지원하여, 유연하고 손쉽게 컴퓨팅 클러스터를 구성하고 활용할 수 있습니다.

이 블로그 시리즈는 EC2 기반의 가속 컴퓨팅 환경을 활용하는 데에 중점을 두고 있습니다. 만약, AWS의 완전 관리형 기계 학습 서비스에 더 많은 관심이 있으시다면 Amazon SageMakerAmazon SageMaker HyperPod을 검토하여 보시기 바랍니다.

AWS ParallelCluster 가속 컴퓨팅 환경 구축

이제부터 ParallelCluster 기반의 가속 컴퓨팅 클러스터를 구축하는 방법에 대해서 알아 보겠습니다. ParallelCluster를 사용하기 위해서는, 먼저 아래의 사전 필요 사항을 충족해야 하며 링크를 참고하여 구성할 수 있습니다.

사전 필요 사항

1. (선택 사항) 온디맨드 용량 예약(On-Demand Capacity Reservations, ODCR) 생성

이 단계는 선택 사항입니다. 가속 컴퓨팅 수요의 급증으로 공급이 원활하지 않은 인스턴스를 사용해야 할 경우에는, 온디맨드 용량 예약을 사용하여 필요한 컴퓨팅 용량을 예약하고 확보할 수 있습니다. 하지만, 용량이 계정에 프로비저닝되면, 인스턴스가 예약 용량으로 실행되는지의 여부와 관계 없이, 선택한 인스턴스 유형에 대한 용량 예약이 온디맨드 요금으로 청구되는 점을 점을 유의해야 합니다. 필요한 인스턴스 유형, 플랫폼, 리전과 가용 영역등을 지정하여 용량 예약을 생성합니다.

aws ec2 create-capacity-reservation \
--instance-type g6.12xlarge \
--instance-platform Linux/UNIX \
--availability-zone us-west-2c \
--instance-count 2 \
--region us-west-2

2. 환경 변수 설정 및 확인

ParallelCluster를 생성하는 데 필요한 환경 변수를 설정합니다. 이를 통하여 클러스터 구성을 보다 자동화할 수 있게 됩니다. 이 단계에서 유의해야 할 사항은, AWS CLI에 사용된 리소스 조회를 위한 인덱스 번호입니다. 사용자의 환경에 맞게 인덱스를 수정하여, 사용하고자 하는 리소스를 지정해 주시기 바랍니다. 또한, 클러스터에 사용할 AWS Deep Learning AMI (DLAMI)의 DLAMI_ID는 DLAMI 릴리즈 노트를 참고하여 조회할 수 있습니다.

CR_ID=$(aws ec2 describe-capacity-reservations --query "CapacityReservations[0].CapacityReservationId" --output text)
VPC_ID=$(aws ec2 describe-vpcs --query "Vpcs[0].VpcId" --output text)
PUB_SUBNET_ID=$(aws ec2 describe-subnets --filters "Name=availability-zone,Values=us-west-2c" --query "Subnets[0].SubnetId" --output text)
KEY_PAIR_NAME=$(aws ec2 describe-key-pairs --query "KeyPairs[0].KeyName" --output text)
DLAMI_ID=$(aws ec2 describe-images --region us-west-2 --owners amazon \
--filters "Name=name,Values=Deep Learning OSS Nvidia Driver AMI GPU PyTorch 2.3.? (Ubuntu 20.04) ????????" "Name=state,Values=available" \
--query "reverse(sort_by(Images, &CreationDate))[:1].ImageId" --output text)

echo $CR_ID
echo $VPC_ID
echo $PUB_SUBNET_ID
echo $KEY_PAIR_NAME
echo $DLAMI_ID

3. 파이썬 가상 환경에 ParallelCluster 설치

가장 먼저 파이썬 가상 환경에 ParallelCluster를 설치합니다. ParallelCluster는 오픈 소스 클러스터 관리 도구로, pip 파이썬 패키지 관리자를 이용하여 손쉽게 설치할 수 있습니다. 설치에 관한 전체 절차는 사용자 가이드를 통해서 확인할 수 있습니다.

mkdir pcluster
python3 -m venv pcluster
source pcluster/bin/activate
cd pcluster
python3 -m pip install --upgrade "aws-parallelcluster"
pcluster version

AWS Cloud Development Kit (AWS CDK) 에서 AWS CloudFormation 템플릿 생성을 위해서 필요한 Node.js를 설치합니다.

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
chmod ug+x ~/.nvm/nvm.sh
source ~/.nvm/nvm.sh
nvm install --lts
node --version

4. 커스텀 AMI 생성

ParallelCluster는 Amazon Linux, Ubuntu, RHEL과 같은 다양한 운영체제 기반의 Amazon Machine Image(AMI)를 제공하고 있으며, 아래의 명령으로 확인할 수 있습니다.

pcluster list-official-images

그러나, 블로그 시리즈의 파트 1에서 확인한 바와 같이, DLAMI를 사용한다면 보다 더 손쉽고 빠르게 환경을 구축할 수 있을 것입니다. 따라서, 이번 단계에서는 클러스터에 사용할 커스텀 이미지를 DLAMI 기반으로 생성할 것이며, 전체 과정은 사용자 가이드에서 확인할 수 있습니다. 다양한 옵션들이 있지만, 가이드의 간소화를 위하여 InstanceTypeParentImage 만 적용하였습니다.

cat > pcluster-dlami.yaml << EOF
Build:
  InstanceType: g6.12xlarge
  ParentImage: ${DLAMI_ID}
EOF

pcluster build-image --image-id dlami-ubuntu-2004-pytorch -c pcluster-dlami.yaml

커스텀 이미지의 생성은 약 1시간 정도가 소요되지만, 이미지 구성에 따라서 달라질 수 있습니다. 아래와 같이 이미지의 생성을 모니터링하고 생성된 이미지의 ID를 환경 변수로 저장합니다.

pcluster list-images --image-status PENDING
pcluster list-images --image-status AVAILABLE

PC_DLAMI=$(pcluster list-images --image-status AVAILABLE | jq -r '.images[0].ec2AmiInfo.amiId')
echo $PC_DLAMI

5. 클러스터 생성

DLAMI를 기반으로 한 커스텀 이미지까지 생성이 완료가 되면, 이제 클러스터를 생성할 준비가 완료되었습니다. 클러스터 생성을 위한 전체 과정은 AWS CLI 사용한 클러스터 생성을 추가로 참고하여 주시기 바랍니다. 이 블로그에서 생성하는 클러스터는 편의를 위하여 모든 인스턴스가 퍼블릭 서브넷에 배치가 됩니다. 하지만, 실제 운영 환경에서는 다른 형태의 네트워크 구성이 필요할 수도 있으며, 네트워크 구성 사용자 가이드를 추가로 참고하여 사용자의 환경에 맞게 구성할 수 있습니다.

아래와 같이 클러스터 생성을 위한 YAML 구성 파일을 생성합니다. 이 클러스터는 하나의 m6i.large 인스턴스를 사용한 헤드 노드, g6.12xlarge 인스턴스를 사용하여 최소 2개에서 최대 4개까지 온디맨드로 확장할 수 있는 컴퓨트 노드로 구성이 됩니다. G6 유형의 인스턴스는 최대 8개의 NVIDIA L4 Tensor Core GPU와 192GB의 GPU 메모리를 제공합니다. 또한, 컴퓨트 노드는 고성능 네트워크 인터페이스인 Elastic Fabric Adaptor(EFA)를 사용하며, Amazon EFS를 공유 스토리지로 사용하는 클러스터를 생성합니다. EFS 파일 시스템은 모든 노드의 /shared 디렉토리에 마운트가 됩니다. 클러스터 구성을 위한 전체 파라미터는 사용자 가이드를 참고하십시오.

EFA와 EFS에 대한 보다 자세한 사항은 “AWS 고성능 컴퓨팅 네트워크, 1부: AWS가 제공하는 고속 네트워크 인터페이스, EFA(Elastic Fabric Adaptor)”와 “Amazon EFS의 처리량 및 성능 모드에 대한 이해와 올바른 선택” 블로그를 참고하실 수 있습니다.

cat > pcluster-g6-efs.yaml << EOF
HeadNode:
  InstanceType: m6i.large
  Imds:
    Secured: true
  Ssh:
    KeyName: ${KEY_PAIR_NAME}
  LocalStorage:
    RootVolume:
      VolumeType: gp3
      Size: 200
  Networking:
    SubnetId: ${PUB_SUBNET_ID}
  Iam:
    AdditionalIamPolicies:
      - Policy: arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
      - Policy: arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess
Scheduling:
  Scheduler: slurm
  SlurmQueues:
    - Name: compute-gpu
      ComputeResources:
        - Name: g6-12xlarge
          InstanceType: g6.12xlarge
          MaxCount: 4
          MinCount: 2
          Efa:
            Enabled: true
      ComputeSettings:
        LocalStorage:
          RootVolume:
            VolumeType: gp3
            Size: 200
#      CapacityReservationTarget:
#        CapacityReservationId: ${CR_ID}
      Networking:
        SubnetIds:
          - ${PUB_SUBNET_ID}
        PlacementGroup:
          Enabled: true
      Image:
        CustomAmi: ${PC_DLAMI}
  SlurmSettings: {}
Region: us-west-2
Image:
  Os: ubuntu2004
  CustomAmi: ${PC_DLAMI}
SharedStorage:
  - Name: pcluster-g6-efs-shared
    StorageType: Efs
    MountDir: /shared
    EfsSettings:
      ThroughputMode: bursting
      PerformanceMode: generalPurpose
      Encrypted: true
      DeletionPolicy: Retain
Monitoring:
  DetailedMonitoring: false
  Logs:
    CloudWatch:
      Enabled: true
  Dashboards:
    CloudWatch:
      Enabled: true
Tags:
  - Key: Name
    Value: pcluster-g6-efs
EOF

만약, 온디맨드 용량 예약을 생성하였다면, 구성 파일의 CapacityReservationTarget, CapacityReservationId의 주석을 제거하고 클러스터를 생성합니다. 아래의 명령으로 생성과 모니터링을 수행할 수 있습니다.

pcluster create-cluster -n pcluster-g6-efs -c pcluster-g6-efs.yaml
pcluster list-clusters

6. 클러스터 헤드 노드 연결 및 확인

ParallelCluster는 AWS Batch와 Slurm 스케줄러를 지원하며, 본 블로그에서는 Slurm이 사용되었습니다. Slurm은 오픈 소스 클러스터 및 작업 스케줄링을 관리하는 워크로드 매니저입니다. 생성된 클러스터는 스케줄러를 이용하여 작업을 제출할 수 있는 헤드 노드와, 작업을 실행하는 컴퓨트 노드로 구성이 되어 있습니다. 우선 헤드 노드에 접속하여 구성된 환경을 확인합니다. 헤드 노드에 SSH로 접속하는 방법은 아래의 2가지 중에 하나를 선택하면 됩니다.

ssh ubuntu@HEAD_NODE_PUBLIC_IP -i KEY_PAIR_NAME.pem
pcluster ssh -n pcluster-g6-efs -i KEY_PAIR_NAME.pem

성공적으로 로그인이 완료되면 운영체제의 MOTD (Message of the Day)를 확인할 수 있습니다. MOTD에서는 운영체제의 기본 정보, DLAMI에 대한 설명, 그리고 PyTorch 가상 환경을 활성화 할 수 있는 명령을 보여줍니다. 추가적으로 파일 시스템 정보를 확인하여, EFS 파일 시스템이 /shared 디렉토리에 정상적으로 마운트가 되어있는지 확인합니다.

df -h

sinfo, squeue, scontrol과 같은 Slurm 명령을 이용하여 클러스터 구성 내역을 확인할 수 있습니다.

sinfo
squeue
scontrol show nodes | grep NodeName

클러스터의 구성이 성공적으로 완료된 것을 확인하였고, 간단한 테스트 작업을 실행해 보겠습니다. 아래와 같이 간단한 배치 스크립트를 작성하고 sbatch를 사용하여 배치 작업을 제출합니다. 이 테스트는 사용자 가이드에서도 확인할 수 있습니다.

cat > hellojob.sh << EOF
#!/bin/bash
sleep 30
echo "Hello World from $(hostname)"
EOF
sbatch hellojob.sh
sinfo
squeue
cat slurm-??.out 

7. 컴퓨트 노드 연결 및 확인

클러스터의 헤드 노드에서 srun 명령을 사용하여 컴퓨트 노드에 연결을 하거나 리소스를 할당 받을 수 있는 다양한 방법이 있습니다. 아래의 명령들을 사용하여, 컴퓨트 노드에 대한 연결을 확인하여 봅니다.

# 임의의 리소스에 대한 터미널 연결
srun --pty bash

# GPU 4개, CPU 48개, 메모리 128GB의 리소스를 할당받고 nvidia-smi 명령 실행
srun --gres=gpu:4 --cpus-per-gpu=12 --mem=128G nvidia-smi

# 특정 노드의 터미널 연결
srun --nodelist=compute-gpu-st-g6-12xlarge-2 --pty bash

현재 구성된 노드들의 파일 시스템 정보를 확인하여, EFS 파일 시스템이 /shared 디렉토리에 정상적으로 마운트가 되어있는지 확인합니다. 또한, 헤드 노드의 /home/opt 디렉토리의 일부가 컴퓨트 노드에 올바르게 공유가 되어 있는지 확인합니다.

df -h

추가적으로 아래의 명령들을 사용하여 장착된 GPU 정보, CUDA 버전 정보, 그리고 EFA도 확인을 합니다. 4개의 NVIDIA L4 GPU와 1개의 EFA가 장착이 되어 있음을 확인할 수 있습니다.

nvidia-smi
nvcc --version
fi_info -p efa -t FI_EP_RDM

이제 클러스터 컴퓨트 노드의 GPU를 테스트할 수 있는 환경의 준비가 완료 되었습니다. 먼저 PyTorch 파이썬 가상 환경을 활성화하고, 아래의 샘플 스크립트를 실행하여 결과를 확인합니다. Conda 환경을 처음 시작할 때 로드가 되는 동안 기다려야 합니다. Conda를 사용한 DLAMI는 프레임워크가 처음 활성화될 때 EC2 인스턴스에 가장 최적화된 버전의 프레임워크를 자동으로 설치합니다. 한번 활성화가 된 이후에는 지연이 발생하지 않습니다.

source activate pytorch

cat << EOF> sample.py
import torch

print("PyTorch Version ->", torch.__version__)
print("GPU 확인 ->", torch.cuda.is_available())
print("GPU 이름 ->", torch.cuda.get_device_name(0))

# GPU 사용 가능 여부 확인
if torch.cuda.is_available():
    device = torch.device('cuda')
    print("GPU를 사용합니다.")
else:
    device = torch.device('cpu')
    print("GPU를 사용할 수 없습니다. CPU를 사용합니다.")

# GPU에서 간단한 텐서 연산
x = torch.tensor([1.0, 2.0, 3.0, 4.0, 5.0], device=device)
y = x ** 2

# 결과 출력
print('입력 텐서:', x)
print('출력 텐서:', y)
EOF
python sample.py

8. 멀티 노드 분산 데이터 병렬 처리

단일 노드에서 단일 GPU를 사용해 보는 테스트를 완료했습니다. 이번에는 2개의 노드와 8개의 GPU를 사용하는 분산 데이터 병렬 처리 테스트를 수행해 보겠습니다. 이는 PyTorch 예제 깃허브의 분산 데이터 병렬 처리 예제를 활용합니다. PyTorch 프레임워크를 사용하여 분산 데이터 병렬 처리를 위한 실습 코드들을 확인할 수 있습니다.

먼저 아래와 같이 헤드 노드에 SSH로 접속하여 깃허브의 코드를 복제합니다. 코드를 복제하는 과정은 깃허브의 클러스터 구성 예제에서 전체 과정을 참고할 수 있습니다.

pcluster ssh -n pcluster-g6-efs -i KEY_PAIR_NAME.pem
cd /shared
git clone --depth 1 https://github.com/pytorch/examples
cd /shared/examples
git filter-branch --prune-empty --subdirectory-filter distributed/ddp-tutorial-series

복제된 깃허브의 sbatch_run.sh를 참고하여 새로운 배치 스크립트를 생성합니다. 이 스크립트는 2개의 노드와 8개의 GPU를 사용하여, torchrun 명령으로 multigpu_torchrun.py를 수행합니다. torchrun 에 대한 개요와 사용 방법은 PyTorch 문서에서 확인할 수 있습니다. 작업이 성공적으로 제출이 되면 8192 번의 Epoch를 수행하며, 1024 번째 Epoch 마다 스냅샷을 저장합니다.

cd /shared/examples/slurm
ls

# 하기의 스크립트 내용으로 새로운 스크립트 파일 생성
vi sbatch_run-01.sh
#!/bin/bash

#SBATCH --job-name=multinode-example
#SBATCH --nodes=2
#SBATCH --ntasks=2
#SBATCH --gpus-per-task=4
#SBATCH --cpus-per-task=4

nodes=( $( scontrol show hostnames $SLURM_JOB_NODELIST ) )
nodes_array=($nodes)
head_node=${nodes_array[0]}
head_node_ip=$(srun --nodes=1 --ntasks=1 -w "$head_node" hostname --ip-address)

echo Node IP: $head_node_ip
export LOGLEVEL=INFO

srun torchrun \
--nnodes 2 \
--nproc_per_node 4 \
--rdzv_id $RANDOM \
--rdzv_backend c10d \
--rdzv_endpoint $head_node_ip:29500 \
/shared/examples/multigpu_torchrun.py 8192 1024

PyTorch 파이썬 가상 환경을 활성화하고, sbatch를 사용하여 배치 작업을 제출합니다.

source activate pytorch
sbatch sbatch_run-01.sh

작업이 수행되는 동안 아래의 명령들을 이용하여, 작업 대기열과 GPU 사용량등의 모니터링이 가능합니다. --nodelist의 노드명은 환경에 맞게 수정합니다.

sinfo
squeue
srun --nodelist=YOUR_COMPUTE_NODE_NAME --pty nvidia-smi

제출된 작업이 성공적으로 완료가 되면, slurm-??.out 결과 파일이 생성되며 아래와 같이 수행결과를 확인할 수 있습니다.

cat slurm-??.out

9. 리소스 정리

실습을 완료하고 테스트 환경을 지속적으로 사용하지 않을 계획이라면, 추가 과금을 방지하기 위하여 ParallelCluster를 삭제하고 온디맨드 용량 예약을 취소합니다.

pcluster delete-cluster -n pcluster-g6-efs
aws ec2 cancel-capacity-reservation --capacity-reservation-id $CR_ID

결론

AWS는 가속 컴퓨팅을 위하여 다양한 유형의 Amazon EC2의 가속 컴퓨팅 인스턴스 뿐만 아니라, 고성능 네트워크 어댑터 Elastic Fabric Adaptor(EFA), 그리고 Amazon EC2 UltraClusters 아키텍처를 사용하여 리소스를 제공합니다. 그러나, 이런 가속 컴퓨팅 리소스를 이용하여 빠르고 효율적으로 환경을 구축하고 활용할 수 있는 방법이 필요합니다.

이를 위하여, AWS는 AWS Deep Learning AMI (DLAMI), Amazon EKS 최적화 가속 Amazon Linux AMI, AWS Deep Learning Containers, 그리고 AWS Batch, AWS ParallelCluster, Amazon EKS와 같은 작업 및 클러스터 관리 도구도 또한 제공하고 있습니다.
이 블로그 시리즈의 “Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 1 – AWS Deep Learning AMI (DLAMI)”에서 DLAMI를 사용하여 가속 컴퓨팅 환경을, 쉽고 빠르게 구축할 수 있는 방법에 대해서 알아 보았습니다. 또한, 지금까지 살펴본 바와 같이 DLAMI의 장점에 더하여 가속 컴퓨팅 클러스터를 손쉽게 구축하고, 유연한 스케일링과 효율적으로 작업을 관리할 수 있는, AWS ParallelCluster를 활용하는 방법을 알아 보았습니다.

마지막으로, 고성능 컴퓨팅(HPC, High Performance Computing) 클러스터 설정과 관리를 지원하는 새로운 관리형 서비스인 AWS Parallel Computing Service (AWS PCS)가 출시가 되었습니다. AWS PCS를 통하여 고성능 가속 컴퓨팅 클러스터 환경을 직접 구축하지 않고도, 관리형 서비스를 이용하여 ParallelCluster의 장점을 누릴 수 있게 되었습니다. 보다 자세한 사항은 “AWS Parallel Computing Service 정식 출시 – 다양한 규모의 HPC 워크로드를 위한 완전 관리서비스” 블로그를 참고하시기 바랍니다.

다음의 블로그 시리즈에서는 컨테이너 환경을 위한 Amazon Elastic Kubernetes Service (EKS) 기반의 GPU 클러스터를 구축하는 방법에 대해서 알아 보겠습니다.

블로그 시리즈

  1. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 1 – AWS Deep Learning AMI (DLAMI)
  2. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 2 – AWS ParallelCluster
  3. Amazon EC2 가속 컴퓨팅 인스턴스 활용하기 – 파트 3 – Amazon Elastic Kubernetes Service (EKS) 기반의 GPU 클러스터
SeungYong Baek

SeungYong Baek

백승용 솔루션즈 아키텍트는 다양한 분야의 IT 인프라 스트럭처와 산업군에 대한 엔지니어 경험을 바탕으로, 고객이 AWS 클라우드를 활용하여 비즈니스 성과를 달성할 수 있도록, 고객과 함께 효율적인 아키텍처를 구성하는 역할을 수행하고 있습니다.

EuiJeong Go

EuiJeong Go

고의정 테크니컬 어카운트 매니저는 다양한 산업군의 IT 시스템 운영 경험을 바탕으로, 엔터프라이즈 기업 고객이 AWS Cloud와 함께 고객의 비즈니스 목표를 달성할 수 있도록 최적화된 성능으로 안정적인 운영 환경을 구축하는 데 도움을 드리고 있습니다.