AMD의 Polaris(gfx800) 아키텍처 GPU에서 ROCm 사용하기

1. ROCm이란?

ROCm은 AMD에서 만든 GPGPU 연산 소프트웨어이다. NVIDIA의 CUDA에 대응하는 프로그램이라고 할 수 있다.

그럼 GPGPU가 뭔데?

GPGPU(General-Purpose computing on Graphics Processing Units, 그래픽 처리 장치의 범용 연산)는 그래픽 처리 장치(GPU)를 그래픽 렌더링 외의 일반적인 계산 작업에 쓰는 기술이다. 원래 GPU는 3D 모델링, 이미지 처리 등 말 그대로 그래픽을 표시하여 사용자에게 보여주기 위해 만들어졌다. 그런데, 이런 비유를 어디선가 들어본 적이 있을 것이다.

CPU는 복잡한 문제도 풀 수 있는 머리가 비상한 아이들이 소수정예로 있는 것이고, GPU는 사칙연산정도만 할 줄 아는 아이들이 수천 수만 명 있는 것이다.

‘이런 GPU를 그래픽 표시하는데 쓰지 말고, 얘네들도 간단한 연산은 할 줄 아니까 연산 작업에 써 보자!’ 라는 아이디어에서 출발한 것이 GPGPU이다. 처음 발상해낸 사람이 누군지는 모르겠지만, 정말 천재적인 능력을 갖고 있는 사람임이 분명하다.

그럼 너네가 뭘 할 수 있는데?

대표적인 것으로는 다음과 같은 일을 비교적 CPU보다 빠르게 할 수 있다:

  1. 과학 계산: 물리학, 화학, 생물학 등의 분야에서 복잡한 수치 계산 및 모의 실험
  2. 데이터 분석: 대규모 데이터 세트의 분석 및 처리
  3. 머신 러닝: 대량의 데이터를 이용한 학습
  4. 암호화 및 보안: 암호화 해독, 해시 계산 등 보안 관련 작업

그렇다. 암호화폐의 폭등으로 "17~18년과 "20~22년에 GPU 구하기가 매우 어려웠었던 이유도 당시 이더리움을 위시한 암호화폐는 사용자들이 했던 거래 내용의 신용을 보증하기 위해 복잡한 수학 문제를 풀어 답을 찾아내고, 그 대가로 암호화폐를 주는 체계를 갖추고 있었는데, 이 복잡한 수학 문제를 GPGPU로 할 수 있기 때문이었다. 아이고… 하필이면 내가 GPU 가격이 고점을 매일 갱신하고 있을 때 컴퓨터를 구비하게 되어 GTX 1060 3GB밖에 살 수 없었는데, 지금 생각해도 참 슬프다.

2. ROCm을 설치하는 방법

AMD는 소프트웨어 지원이 타사 대비 빈약하다. 옛날부터 컴퓨터를 다뤄왔던 사람이라면, AMD의 Catalyst라는 GPU 드라이버를 잘 알 것이다. Catalyst는 물리화학에서 촉매를 뜻하는데, 말 그대로 '지금까지의 GPU 드라이버를 뛰어넘는 기폭제가 되겠다!'는 뜻으로 그런 이름을 지은 것 같다. 하지만, 현실은 그렇지 않았다. 한번 어긋나기 시작하면 잦은 오류 발생, 타 프로그램(심지어 운영체제까지!)과의 충돌 등이 일어나 제대로 동작시키기 매우 어려워 당시 사람들은 '카탈리스트’는 안정화하여 쓰기 매우 까탈스럽다 하여 '까탈리스트’라고 불렀다.

ROCm도 마찬가지이다. AMD와 경쟁 관계에 있는 NVIDIA는 출시한지 10년이 지난 GPU도 자사의 GPGPU 소프트웨어인 CUDA를 지원하지만, AMD는 출시한지 오래되지 않은 GPU라 할지라도 ROCm 지원을 중단했다.

그래서, 우리가 사용할 Polaris 아키텍처의 GPU는 이미 지원 중단된지 오래됐으므로, "20년 4월에 출시된 Ubuntu 20.04를 사용할 것이다. Ubuntu 20.04의 코드네임은 'Focal Fossa’인데, 주로 마다가스카르에 서식하는 야옹이를 닮은 동물이라고 한다. 평균 몸무게는 6kg이며, 평균 몸 길이는 75cm 정도인데, 놀라운 점은 꼬리 길이가 몸 길이와 비슷하다는 것이다. 역시 동물의 세계는 놀랍다.

1. Ubuntu 20.04 설치

Ubuntu 웹사이트에 접속해 다운로드를 한 뒤, 컴퓨터에서 부팅하여 설치를 진행한다. 친절한 설치 프로그램이 자동으로 실행되므로, 이 과정의 설명은 생략한다.

2. 시스템 업데이트 및 필요 라이브러리 다운로드

Ubuntu를 설치했으면, 이제 시스템을 업데이트해야 한다. 다음 명령을 차례대로 실행한다.

sudo apt update
sudo apt full-upgrade

'full upgrade’라는 말 그대로 Ubuntu 시스템을 이루는 모든 것을 업데이트한다.

이제 ROCm 설치에 필요한 라이브러리를 설치해 보자.

sudo apt install libnuma-dev

자, 시스템도 업데이트했고, 필요한 라이브러리도 설치했으니 한번 다시 시작을 해 준다.

sudo reboot

3. ROCm에 맞는 Linux kernel 설치

커널(Kernel)은 운영체제의 심장과도 같은 매우 중요한 소프트웨어다. 필요한 곳으로 자원을 나누어 주고, 작업을 관리하는 등 여러 작업을 수행한다. 이런 중요한 기능을 수행하고 있기에 ROCm에 맞는 커널로 운영체제가 작동하고 있는 것이 아니면 ROCm이 동작하지 않는다.

우리가 설치할 ROCm과 맞는 리눅스 커널은 5.4.0-42이다. 이 커널을 설치하자.

sudo apt install linux-headers-5.4.0-42-generic \
linux-image-5.4.0-42-generic \
linux-modules-5.4.0-42-generic \
linux-modules-extra-5.4.0-42-generic

그런데, 여기서 의문을 가지는 경우가 있을 것이다. ‘어라? 분명 커널은 하나이지 않나?’ 하지만, 리눅스는 여러 요소들이 모여 커널을 만든다. 각각의 구성요소(패키지)는 다음과 같은 목적을 가지고 있다:

  • headers: 헤더 파일을 포함한 패키지다. C언어를 배웠다면 STanDard Input Output(표준 입·출력)을 담당하는 'stdio.h’를 위시한 '헤더 파일’이라는 것을 들어본 적이 있을 것이다. 헤더 파일은 유용한 도구가 들어가 있는 상자라고 할 수 있다. 프로그램은 이 상자에 든 도구를 사용해 만드는 경우가 대부분이다.
  • image: 실제 리눅스 커널 이미지가 담긴 패키지다. 즉, 담백한 리눅스 커널이라고 할 수 있다. 이 커널 이미지는 컴퓨터가 부팅될 때 메모리에 로드되어 하드웨어와 소프트웨어 간의 상호작용을 관리하게 된다.
  • modules: 기본 커널 모듈이 담긴 패키지다. 모듈은 커널의 기능을 확장하기 위해 만들어진 것으로, 하드웨어 드라이버, 파일 시스템 드라이버 등이 담겨있다.
  • modules-extra: 추가적인 커널 모듈이 담긴 패키지다. 특정한 하드웨어나 기능을 사용하기 위해 필요한 모듈이 담겨있다.

4. ROCm에 맞는 커널을 제외한 다른 커널 제거

이제 다른 커널은 필요하지 않게 되었다. 그러니, 다른 커널은 제거하도록 하자. 다음 명령어를 입력해 보자.

dpkg --list | grep linux-image

그럼, 다음과 같은 것이 출력될 것이다.

rc  linux-image-6.2.0-20-generic 6.2.0-20.20 amd64 Signed kernel image generic
rc  linux-image-6.2.0-23-generic 6.2.0-23.23 amd64 Signed kernel image generic
rc  linux-image-6.2.0-24-generic 6.2.0-24.24 amd64 Signed kernel image generic

환경에 따라 하나만 출력될 수도 있고, 여러개가 출력될 수 있다. 버전이 다를 수도 있다. 자, 이제 우리는 만약 'linux-image-6.2.0-20-generic’이라는 것이 있다면 6.2.0-20 위치에 있는 문자열을 주목할 것이다. 여러개가 출력된다면, 동일한 위치에 있는 문자열들을 주목하자.

이제 아까 설치했던 5.4.0-42 버전을 제외한 모든 커널을 제거하자. 예를 들어, 5.4.0-172라는 것이 있을 경우 다음과 같은 명령을 실행하자:

sudo apt purge *5.4.0-172*

커널이 여러개 있을 경우에는 여러번 반복한다.

자, 이제 커널을 모두 지웠으니 GRUB 설정을 업데이트해줘야 한다.

GRUB가 뭔데?

GRUB(GRand Unified Bootloader)는 리처드 스톨먼(Richard Stallman)이라는 프로그래머가 만든 자유 소프트웨어 재단에서 만든 부트로더이다. 부트로더는 컴퓨터가 켜진 후 운영체제를 메모리에 로드하고 실행하는 매우 중요한 역할을 하는 프로그램이다. 옛날 옛날 아주 먼 옛날, 486 컴퓨터가 왕성히 활동하던 시절, LILO(LInux LOader)라는 부트로더가 리눅스의 부트로더를 지배하고 있었다. LILO를 건들 수 있는 자는 아무도 없었다. 그런데, GRUB가 나타나 LILO에게 뺨따귀를 후려갈기고 LILO의 자리를 차지했다. 왜 그렇게 할 수 있었을까? 그 이유 중 대표적인 몇 가지가 있다:

  1. 설정의 유연성
    LILO는 설정을 변경할 때마다 다시 설치해야 하지만, GRUB는 그럴 필요가 없다.

  2. 부트 기능과 호환성
    LILO는 다룰 수 있는 부팅 설정과 커널 이미지 수의 제한이 있지만, GRUB는 모듈로 구성되어 있어 다양한 파일 시스템과 하드웨어를 지원해 그런 제한이 거의 없다.

  3. 복구와 디버깅 기능
    LILO는 부팅 과정에서 문제를 진단하고 해결할 수 있는 방법이 제한적이나, GRUB는 부팅 시 CLI(Command Line Interface) 환경 즉, Microsoft Windows의 명령 프롬프트같은 환경을 제공하여 부팅 옵션을 수정하거나 특정 부팅 모듈을 더하거나 뺄 수 있고, 문제를 해결할 수 있는 디버깅 도구도 있다.

그래서 LILO는 GRUB가 없는 시대에 태어났을 뿐인 범부(凡夫)라고 할 수 있다. 참으로 슬픈 이야기다.

아무튼, 이제 GRUB 설정을 업데이트해보자.

sudo update-grub

이제 ROCm에 알맞은 커널로 리눅스가 동작해야 하므로, 다시 시작을 해 준다.

sudo reboot

5. ROCm 리포지토리 추가 및 설치

자, 드디어 설치할 환경이 갖추어졌다. 다음 명령어를 입력해 ROCm의 리포지토리(Repository, 데이터 보관 장소)를 Ubuntu가 쓰는 소프트웨어 패키지 관리 도구인 apt에게 알려주자.

wget -qO - https://repo.radeon.com/rocm/rocm.gpg.key | gpg --dearmor | sudo tee /usr/share/keyrings/rocm-archive-keyring.gpg > /dev/null

echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/rocm-archive-keyring.gpg] http://repo.radeon.com/rocm/apt/3.5.1/ xenial main' | sudo tee /etc/apt/sources.list.d/rocm.list

이제, apt에게 리포지토리들을 새로 확인하라고 하고, ROCm의 DKMS(Dynamic Kernel Module Support)을 설치하자.

DKMS가 뭔데?

DKMS는 커널의 기능을 확장하기 위해 만들어진 모듈 중 특정 모듈을 전체 커널을 수정할 필요 없이 더하거나 수정할 수 있도록 해 주는 기능이다.

sudo apt update
sudo apt install rocm-dkms

DKMS는 커널의 모듈을 수정하므로, 수정하는데 적절한 시간이 소요된다. 적당히 이콜라, 에고체이서, 미티어라이트, 파인트 앤 쿼츠, 레드우드 팩, 피스와서 중 하나를 골라 섭취하면서 기다리도록 하자.

모든 작업이 끝났다면, 사용자인 나 자신을 적절한 그룹에 포함해줘야 한다. 다음 명령을 실행하자:

sudo usermod -aG video $LOGNAME
sudo usermod -aG render $LOGNAME

video랑 render 그룹이 뭔데?

  • video: 비디오 하드웨어에 접근 가능한 권한이 있는 사용자들의 그룹이다. 이 그룹에 속하게 되면 일반적으로 GPU와 같은 비디오 관련 하드웨어 설정을 변경하거나 관리할 수 있으며, 디스플레이 해상도를 변경하거나 GPU 드라이버 설정을 조작하는 등의 행동을 할 수 있다.

  • render: 리눅스 커널의 서브 시스템 중 하나이며 비디오 하드웨어를 제어하기 위한 커널 드라이버인 DRM(Direct Rendering Manager)에 접근 가능한 권한이 있는 사용자들의 그룹이다. 이 그룹에 속하게 되면 일반적으로 그래픽 렌더링 등 그래픽 작업을 처리할 수 있게 되며, GPU 가속(GPGPU 등)도 할 수 있게 된다.

이제 이 권한을 나에게 부여해 줬으니, 재부팅을 해서 권한 설정을 적용해 주자.

sudo reboot

6. ROCm의 OpenCL 기능 설치

OpenCL은 GPGPU 프로그래밍에 사용되는 API(Application Programming Interface)중 하나이다. API를 사용하게 되면 하드웨어를 직접 제어하지 않고, 추상화하여 제어할 수 있게 된다. 예를 들면, 원래는 ‘오른팔을 20cm 앞으로 뻗고, 오른팔을 5cm 내리고, 오른손으로 겨울배를 집고, 오른팔을 10cm 올리고, 오른팔을 30cm 뒤로 오게 하고, 입을 열고, 오른팔을 10cm 더 뒤로 오게 하고, 오른손에서 겨울배를 놓고, 오른팔을 10cm 앞으로 오게 하고, 입을 닫고, 섭취 행동을 실시한다’ 라고 해야 한다면, API를 쓰면 ‘20cm 앞에 있는 겨울배를 집어서 먹어’ 로 추상화하여 전달할 수 있다! 즉, 알아서 잘 딱 깔끔하고 센스있게 명령을 내릴 수 있게 되는 것이다. 또 다른 예시로, ‘지금 뭐 드시고 있는지 세 번째 물어봅니다’ 라는 질문이 들어왔을 때, 일일히 입을 열고, 혀를 앞으로 하여… 와 같은 명령을 내리지 않고, API를 사용하여 ‘배 먹어 배!’ 라고 말하라고만 시키면 된다.

OpenCL을 자동으로 설치하는 스크립트를 실행하고, 리눅스 시스템에 쓰이는 공유 라이브러리의 링크를 생성 및 업데이트하고, 공유 라이브러리의 캐시를 생성 및 업데이트하자.

echo 'export PATH=$PATH:/opt/rocm/bin:/opt/rocm/profiler/bin:/opt/rocm/opencl/bin' | sudo tee -a /etc/profile.d/rocm.sh
sudo ldconfig

이제 OpenCL API가 설치되었으니, 시스템에 잘 적용하기 위해 다시 시작을 해 주자.

sudo reboot

7. ROCm 및 OpenCL 작동 확인

다음 명령을 입력해 ROCm 정보를 확인할 수 있다:

rocminfo

그러면, 다음과 비슷한 내용이 출력될 것이다:

==========
HSA Agents
==========
*******
Agent 1
*******
  Name:  gfx803  
  Uuid:  GPU-XX  
  Marketing Name: Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]
  Vendor Name: AMD  
  Feature:  KERNEL_DISPATCH  
  Profile:  BASE_PROFILE  
  Float Round Mode:  NEAR 
  Max Queue Number:  128(0x80)  
  Queue Min Size: 4096(0x1000)  
  Queue Max Size: 131072(0x20000)  
  Queue Type:  MULTI
  Node:  1 
  Device Type: GPU
(이하생략)

축하한다! 당신은 이제 ROCm을 사용해 GPGPU 연산을 할 수 있다!

자, 그럼 OpenCL 정보도 확인해 보자. OpenCL 정보를 확인하기 위해서 패키지 하나를 설치해줘야 한다.

sudo apt install clinfo
clinfo

그러면, 다음과 비슷한 내용이 출력될 것이다:

Number of platforms                               1
  Platform Name                                   AMD Accelerated Parallel Processing
  Platform Vendor                                 Advanced Micro Devices, Inc.
  Platform Version                                OpenCL 2.0 AMD-APP (3137.0)
  Platform Profile                                FULL_PROFILE
  Platform Extensions                             cl_khr_icd cl_amd_event_callback 
  Platform Extensions function suffix             AMD
  
(생략)

  Platform Name                                   AMD Accelerated Parallel Processing
Number of devices                                 1
  Device Name                                     gfx803
  Device Vendor                                   Advanced Micro Devices, Inc.
  Device Vendor ID                                0x1002
  Device Version                                  OpenCL 1.2 
  Driver Version                                  3137.0 (HSA1.1,LC)
  Device OpenCL C Version                         OpenCL C 2.0 
  Device Type                                     GPU
  Device Board Name (AMD)                         Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]
  Device Topology (AMD)                           PCI-E, 01:00.0

(이하생략)

축하한다! 당신은 이제 OpenCL을 사용해 GPGPU 연산을 할 수 있다!

8. 커널 업데이트 방지

모든 운영체제가 마찬가지지만, 주기적으로 커널이 업데이트된다. 운영체제는 가능한 한 시스템을 최신으로 유지하려고 한다. 하지만, 아까 설명한것처럼 ROCm은 특정 커널 버전에서만 작동한다. 따라서, 다른 패키지는 업데이트하더라도 커널만은 업데이트하지 마라고 말해둬야 한다.

sudo apt-mark hold linux-image-$(uname -r)
sudo apt-mark hold linux-headers-$(uname -r)
sudo apt-mark hold linux-modules-$(uname -r)
sudo apt-mark hold linux-modules-extra-$(uname -r)

그리고, 패키지 관리자인 apt가 내 말을 잘 이해했는지 확인하기 위해 업데이트 방지가 되어 있는 패키지의 목록을 말하도록 시키자.

apt-mark showhold

다음과 같이 나온다면 성공한 것이다:

linux-headers-5.4.0-42-generic
linux-image-5.4.0-42-generic
linux-modules-5.4.0-42-generic
linux-modules-extra-5.4.0-42-generic

만약, 정말 만약에 ROCm 사용을 포기하고 커널을 업데이트하려고 한다면, 다음 명령을 실행해주면 된다:

sudo apt-mark unhold {패키지_이름}

마치며…

이 글에는 ROCm과 OpenCL을 구형 아키텍처의 GPU에서 사용하기 위한 방법을 담았다. 이 글을 통해 RX 500 GPU에서 GPGPU를 구동해 보려는 사람들에게 도움이 되었으면 좋겠다.

4개의 좋아요

와 글 개쌈@뽕;
방치중이던 RX580 전직 채굴 노동자 다시 일이나 시켜야겠다

확인사살을 하는 나 ㄷㄷ