CUDA, ROCm, oneAPI? — GPU, 모든 GPU에서 코드 실행
여러 공급업체의 GPU 프로그래밍 모델을 아는 것이 필요악인 이유는 무엇입니까?
소개
병렬 및 가속기 프로그래밍에 대한 지난 두 게시물 에서 가속기 및 병렬 프로그래밍의 기본 사항과 코드의 정확성을 보장하는 데 필요한 일부 프로그래밍 개념에 대해 이야기했습니다. 가속기 프로그래밍을 배우는 프로그래머에게 흥미로운 질문은 "NVIDIA, AMD 및 Intel 가속기 프로그래밍을 위해 CUDA, ROCm 및 SYCL을 배워야 합니까?"입니다.
이 시리즈를 계획할 때 각 아키텍처의 하드웨어 실행과 메모리 모델 간의 유사점과 차이점에 대해 자세히 알아보려고 했습니다. 하드웨어 스레드에서 실행을 그룹화하기 위해 CUDA, ROCm 및 SYCL이 사용하는 각각의 구성인 워프, 웨이브프론트 및 작업 그룹에 대해 이야기하려고 했습니다. 그러나 생각하면 할수록 블로그 게시물에 너무 많은 것 같습니다. 이러한 주제에 관심이 있는 경우 Codeplay에서 CUDA 개발자를 위한 멋진 SYCL을 참조하십시오.
대신 오늘은 코드가 없는 상태에서 가능한 한 빨리 GPU, 모든 GPU에서 실행하는 방법에 초점을 맞출 것입니다. 가속기의 성능 이점을 가능한 한 빨리 확인하는 것만큼 재미있는 것은 없습니다. 저에게는 이것이 NVIDIA용 Codeplay oneAPI 및 AMD용 oneAPI(베타) 출시와 일치하기 때문에 재미 있습니다.
SYCL 및 여러 벤더 GPU
SYCL은 NVIDIA, AMD 및 Intel GPU에 대한 컴파일러 지원이 있는 프로그래밍 모델입니다. SYCL에서 코드를 작성한 다음 해당 공급업체 GPU에서 빌드하고 실행할 수 있습니다. 이전에는 GPU 대상에 따라 다양한 커뮤니티 컴파일러를 사용하거나 인텔 오픈 소스 컴파일러를 구축해야 했습니다. 최신 Codeplay 도구 체인의 출시로 이제 사전 빌드된 단일 도구 체인을 통해 코드를 쉽고 빠르게 실행할 수 있습니다. 이에 대한 자세한 내용은 Codeplay의 CTO인 Ruyman Reyes 의 새 릴리스 블로그 에서 확인할 수 있습니다.
당신이 물어볼 수 있는 한 가지 질문은 실제로 내 코드를 한 번 빌드한 다음 런타임에 실행할 GPU를 결정할 수 있습니까? 대답은 예 입니다! 이것은 이 지원에 대한 좋은 점입니다. 코드를 한 번 빌드하고 런타임에 대상을 수동으로 선택하거나 런타임 라이브러리가 자동으로 선택하도록 할 수 있습니다.
당신이 여기까지 왔기 때문에 이것이 당신에게 관심이 있다고 가정하고 내 목표는 당신이 선택한 GPU에서 시작하고 실행하는 것입니다. 내 목적을 위해 Ubuntu 22.04에서 3개의 공급업체 GPU를 모두 테스트하고 APT를 통해 설치를 수행하고 있습니다.
Codeplay 툴체인 설치
먼저 몇 가지 기본 시스템 패키지를 설정합니다.
sudo apt update
sudo apt -y install cmake pkg-config build-essential
# download the key to system keyring
wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB \
| gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
# add signed entry to apt sources and configure the APT client to use Intel repository:
echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
sudo apt-update
sudo apt install intel-basekit
가지고 있거나 목표로 삼고 싶은 각 GPU에 필요한 기본 드라이버/프레임워크가 있는지 확인하십시오. 다시 Ubuntu 지침을 연결하고 있습니다.
인텔 GPU 드라이버 설치
다른 OS의 Intel GPU에 대한 지침은 여기 에서 찾을 수 있습니다 . Ubuntu 22.04에서 Intel Arc를 사용하고 있기 때문에 다음 지침 을 따랐습니다 .
NVIDIA 설치용 oneAPI
여기 로 이동 하여 CUDA 설치 방법에 대한 최신 공식 지침을 얻을 수 있습니다. 저는 이를 설치하고 실행하는 데 사용하는 것을 인라인하고 있습니다.
- CUDA 키링 설치, CUDA 및 재부팅
wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb
sudo dpkg -i cuda-keyring_1.0-1_all.deb
sudo apt-get update
sudo apt-get install cuda-11-7
sudo apt-get install nvidia-gds
sudo reboot
export PATH=/usr/local/cuda-11.7/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-11.7/lib64\
${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
sh oneapi-for-nvidia-gpus-2023.0.0-linux.sh
. /opt/intel/oneapi/setvars.sh --include-intel-llvm
export PATH=/usr/local/cuda-11.7/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-11.7/lib64\
${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
여기 로 이동 하여 ROCm 설치 방법에 대한 최신 공식 지침을 얻을 수 있습니다. 작업을 좀 더 쉽게 하기 위해 다시 여기에 인라인합니다.
- APT를 통해 AMD amdgpu-install 프로그램을 설치합니다.
sudo apt-get update
wget https://repo.radeon.com/amdgpu-install/5.4.1/ubuntu/jammy/amdgpu-install_5.4.50401-1_all.deb
sudo apt-get install ./amdgpu-install_5.4.50401-1_all.deb
amdgpu-install --usecase="dkms,graphics,opencl,hip,hiplibsdk"
sh oneapi-for-amd-gpus-2023.0.0-linux.sh
. /opt/intel/oneapi/setvars.sh --include-intel-llvm
export PATH=/PATH_TO_ROCM_ROOT/bin:$PATH
export LD_LIBRARY_PATH=/PATH_TO_ROCM_ROOT/lib:$LD_LIBRARY_PATH
오픈 소스 oneAPI 샘플 GitHub 리포지토리에서 시도할 수 있는 다양한 코드 샘플이 있습니다.
Codeplay 예제에서 이 simple-sycl-app.cpp를 생성한 것을 볼 수 있습니다.
#include <sycl/sycl.hpp>
int main() {
// Creating buffer of 4 ints to be used inside the kernel code
sycl::buffer<sycl::cl_int, 1> Buffer(4);
// Creating SYCL queue
sycl::queue Queue;
// Size of index space for kernel
sycl::range<1> NumOfWorkItems{Buffer.size()};
// Submitting command group(work) to queue
Queue.submit([&](sycl::handler &cgh) {
// Getting write only access to the buffer on a device
auto Accessor = Buffer.get_access<sycl::access::mode::write>(cgh);
// Executing kernel
cgh.parallel_for<class FillBuffer>(
NumOfWorkItems, [=](sycl::id<1> WIid) {
// Fill buffer with indexes
Accessor[WIid] = (sycl::cl_int)WIid.get(0);
});
});
// Getting read only access to the buffer on the host.
// Implicit barrier waiting for queue to complete the work.
const auto HostAccessor = Buffer.get_access<sycl::access::mode::read>();
// Check the results
bool MismatchFound = false;
for (size_t I = 0; I < Buffer.size(); ++I) {
if (HostAccessor[I] != I) {
std::cout << "The result is incorrect for element: " << I
<< " , expected: " << I << " , got: " << HostAccessor[I]
<< std::endl;
MismatchFound = true;
}
}
if (!MismatchFound) {
std::cout << "The results are correct!" << std::endl;
}
return MismatchFound;
}
일반적으로 다양한 대상을 빌드하기 위해 다음과 같은 명령줄을 사용할 수 있습니다.
엔비디아:
clang++ -fsycl -fsycl-targets=nvptx64-nvidia-cuda simple-sycl-app.cpp -o simple-sycl-app
clang++ -fsycl -fsycl-targets=amdgcn-amd-amdhsa -Xsycl-target-backend --offload-arch=<ARCH> simple-sycl-app.cpp -o simple-sycl-app
clang++ -fsycl -fsycl-targets=spir64 simple-sycl-app.cpp -o simple-sycl-app
여러 벤더 GPU를 위한 빌드
NVIDIA와 Intel GPU에서 동시에 실행하고 싶다고 가정해 보겠습니다. 실제로 NVIDIA 또는 Intel GPU에서 실행되는 팻 바이너리를 만들 수 있습니다. 여기서 요령은 여러 SYCL 대상을 갖도록 빌드 명령줄 매개변수를 적절하게 설정하는 것입니다.
clang++ -fsycl -fsycl-targets=nvptx64-nvidia-cuda,spir64 simple-sycl-app.cpp -o simple-sycl-app
tonym@LianLi-Linux:~/dev/2023.0Test$ clang++ -fsycl -fsycl-targets=nvptx64-nvidia-cuda,spir64 simple-sycl-app.cpp -o simple-sycl-app
tonym@LianLi-Linux:~/dev/2023.0Test$ SYCL_DEVICE_FILTER=cuda SYCL_PI_TRACE=1 ./simple-sycl-app
SYCL_PI_TRACE[basic]: Plugin found and successfully loaded: libpi_cuda.so [ PluginVersion: 11.15.1 ]
SYCL_PI_TRACE[all]: Selected device: -> final score = 1500
SYCL_PI_TRACE[all]: platform: NVIDIA CUDA BACKEND
SYCL_PI_TRACE[all]: device: NVIDIA GeForce RTX 3080 Ti
The results are correct!
tonym@LianLi-Linux:~/dev/2023.0Test$
tonym@LianLi-Linux:~/dev/2023.0Test$ SYCL_DEVICE_FILTER=ext_oneapi_level_zero:gpu:0 SYCL_PI_TRACE=1 ./simple-sycl-app
SYCL_PI_TRACE[basic]: Plugin found and successfully loaded: libpi_level_zero.so [ PluginVersion: 11.15.1 ]
SYCL_PI_TRACE[all]: Selected device: -> final score = 1550
SYCL_PI_TRACE[all]: platform: Intel(R) Level-Zero
SYCL_PI_TRACE[all]: device: Intel(R) Graphics [0x56a0]
The results are correct!
미래의 일
몇몇 기민한 독자들은 내가 멀티벤더 GPU 예제에 AMD 예제를 포함하지 않았다는 것을 눈치챘을 것입니다. 최근에 AMD 6800XT GPU를 새로운 AMD RX 7900XT GPU로 교체했기 때문입니다. 불행하게도 ROCm은 RDNA3 카드와 함께 사용하는 커널에 관계없이 현재 Linux 시스템에 제대로 설치되지 않습니다. 이것이 업데이트되면 돌아와서 3개의 카드 모두에서 실행되는 예제와 함께 지침을 제공할 것입니다.
이전에 이 흐름의 버전은 6800XT에서 작동했지만 여기에 문서화된 오픈 소스 DPC++ 흐름을 사용하여 Codeplay 소프트웨어가 출시되기 전이었습니다.
결론
Codeplay의 NVIDIA GPU용 oneAPI를 사용하여 NVIDIA 또는 Intel GPU용 바이너리를 쉽게 만들 수 있었습니다. NVIDIA GPU용 추가 oneAPI를 설정하는 시간은 Intel oneAPI Base Toolkit을 설치하는 시간 외에 약 10분이었습니다. 여기에는 CUDA 및 Codeplay 소프트웨어 설치가 포함되었습니다.
새로운 Codeplay 소프트웨어는 멀티벤더 GPU 옵션을 고려하는 개인과 회사를 위한 새로운 옵션을 제공합니다. 옵션이 오픈 소스가 되기 전에는 커뮤니티에서 지원하는 컴파일러였습니다. 이것은 환상적인 옵션이며 일상적인 작업에 일반적으로 사용하는 것입니다.
그러나 장기적인 지원을 고려하는 사람들의 경우, 일명 비즈니스는 Codeplay에서 공식적으로 지원되는 옵션을 통해 생계를 유지하기 위해 도구 체인에 의존하게 되며 인텔은 마음의 평화를 제공하는 데 도움이 될 수 있습니다.
내가 읽고 있는 임의의 기술 뉴스를 보고 싶다면 Twitter에서 나를 팔로우할 수 있습니다. 또한 제가 호스팅하는 개발자를 위한 Intel 팟캐스트인 Code Together 를 확인하십시오.
Tony는 인텔의 소프트웨어 설계자이자 기술 전도사입니다. 그는 Intel VTune Profiler 및 기타 성능 도구의 설계자였으며 가장 최근에는 Habana의 확장 가능한 MLPerf 솔루션을 지원하는 데이터 센터 플랫폼을 구축한 소프트웨어 엔지니어링 팀을 이끌었습니다.

![연결된 목록이란 무엇입니까? [1 부]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































