CUDA, ROCm, oneAPI? — Executando código em uma GPU, qualquer GPU
Por que conhecer o modelo de programação de GPU de vários fornecedores é um mal necessário... ou é?
Introdução
Em meus dois últimos posts sobre programação paralela e aceleradora, falei sobre os fundamentos da programação paralela e do acelerador e alguns dos conceitos de programação necessários para garantir a correção do seu código. A pergunta interessante para o programador que está aprendendo a programar aceleradores é “Eu realmente preciso aprender CUDA, ROCm e SYCL para programar para aceleradores NVIDIA, AMD e Intel?”
Ao planejar esta série, esperava mergulhar nas semelhanças e diferenças entre a execução de hardware e os modelos de memória de cada arquitetura. Eu ia falar sobre warps, wavefronts e workgroups, as respectivas construções que CUDA, ROCm e SYCL usam para agrupar a execução em threads de hardware. No entanto, quanto mais penso nisso, mais parece um pouco demais para um post de blog. Se você estiver interessado nesses tópicos, consulte o SYCL para desenvolvedores CUDA da Codeplay.
Em vez disso, hoje vou me concentrar em como passar de nenhum código para execução em uma GPU, qualquer GPU, o mais rápido possível. Nada é tão divertido quanto ver os benefícios de desempenho do seu acelerador o mais rápido possível. Para mim, isso é divertido porque coincide com o lançamento do Codeplay oneAPI para NVIDIA e oneAPI para AMD (beta) .
SYCL e GPUs de vários fornecedores
SYCL é um modelo de programação que possui suporte de compilador para GPUs NVIDIA, AMD e Intel. Você pode escrever seu código em SYCL e, em seguida, construí-lo e executá-lo nas GPUs desses fornecedores. Anteriormente, isso exigia o uso de vários compiladores da comunidade ou a criação do compilador Intel Open Source, dependendo do destino da GPU. Com o lançamento das mais recentes cadeias de ferramentas do Codeplay, agora você pode executar seu código de forma rápida e fácil por meio de uma única cadeia de ferramentas pré-construída. Para mais detalhes sobre isso, você pode ler o blog de Ruyman Reyes, CTO da Codeplay, em seu novo lançamento.
Uma pergunta que você pode estar se perguntando é: posso realmente criar meu código uma vez e depois decidir em tempo de execução em qual GPU executar? A resposta é SIM ! Isso é bom sobre esse suporte, você cria seu código uma vez e no tempo de execução, pode escolher seu destino manualmente ou deixar a biblioteca de tempo de execução escolher automaticamente para você.
Como você chegou até aqui, presumo que seja do seu interesse e meu objetivo é colocá-lo em funcionamento na GPU de sua escolha. Para meus propósitos, estou testando todas as 3 GPUs de fornecedores no Ubuntu 22.04 e fazendo a instalação via APT.
Instalando a cadeia de ferramentas Codeplay
Primeiro, configuramos alguns pacotes básicos do sistema:
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
Certifique-se de ter os drivers/frameworks básicos necessários para cada GPU que você possui/deseja segmentar, novamente estou vinculando as instruções do Ubuntu:
Instalação do driver da GPU Intel
As instruções para GPUs Intel em diferentes sistemas operacionais podem ser encontradas aqui . Como estou usando um Intel Arc no Ubuntu 22.04, segui estas instruções .
instalação oneAPI para NVIDIA
Você pode acessar aqui para obter as instruções oficiais mais recentes sobre como instalar o CUDA, estou inserindo o que uso para colocá-lo em funcionamento:
- Instale o chaveiro CUDA, CUDA e reinicie
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}}
Você pode ir aqui para obter as instruções oficiais mais recentes sobre como instalar o ROCm, novamente inlining aqui para tornar as coisas um pouco mais fáceis para você:
- Instale o programa AMD amdgpu-install via APT
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
Há muitos exemplos de códigos diferentes que você pode experimentar no repositório GitHub de amostras oneAPI de código aberto:
No exemplo Codeplay, você pode ver que eles criaram este 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;
}
Normalmente, para construir nossos vários alvos, podemos usar linhas de comando parecidas com esta:
NVIDIA:
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
Criação para GPUs de vários fornecedores
Digamos que eu queira executar GPUs NVIDIA e Intel ao mesmo tempo. Na verdade, posso criar um binário gordo que será executado em uma GPU NVIDIA ou Intel. O truque aqui é definir os parâmetros da linha de comando de construção apropriadamente para ter vários destinos 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!
Trabalho futuro
Alguns leitores astutos podem perceber que não incluí um exemplo de AMD em meu exemplo de GPU de vários fornecedores. Isso acontece porque recentemente substituí a GPU AMD 6800XT por uma nova GPU AMD RX 7900XT. Infelizmente, o ROCm atualmente não é instalado corretamente no meu sistema Linux, independentemente do kernel que estou usando com a placa RDNA3. Assim que isso for atualizado, voltarei e fornecerei instruções com um exemplo em execução em todos os 3 cartões.
Observe que anteriormente uma versão desse fluxo funcionava para o 6800XT, mas isso foi antes do software Codeplay ser lançado usando o fluxo DPC++ de código aberto documentado aqui:
Conclusão
A oneAPI para GPUs NVIDIA da Codeplay me permitiu criar binários para GPUs NVIDIA ou Intel facilmente. O tempo para configurar o oneAPI adicional para GPUs NVIDIA foi de cerca de 10 minutos além do tempo para instalar o Intel oneAPI Base Toolkit. Isso incluiu a instalação do CUDA e do software Codeplay.
O novo software Codeplay abre uma nova opção para indivíduos e empresas que consideram opções de GPU de vários fornecedores. Antes, as opções eram de código aberto, compiladores suportados pela comunidade. Esta é uma opção fantástica e o que eu normalmente uso para o trabalho do dia-a-dia.
No entanto, para pessoas que consideram suporte de longo prazo, também conhecidas como empresas, dependem de cadeias de ferramentas para sua subsistência, ter uma opção com suporte oficial do Codeplay e da Intel pode ajudar a proporcionar tranquilidade.
Se você quiser ver quais notícias aleatórias de tecnologia estou lendo, pode me seguir no Twitter. Além disso, confira o Code Together , um podcast da Intel para desenvolvedores que eu hospedo, onde conversamos sobre tecnologia.
Tony é arquiteto de software e evangelista técnico da Intel. Ele foi o arquiteto do Intel VTune Profiler e outras ferramentas de desempenho e, mais recentemente, liderou a equipe de engenharia de software que construiu a plataforma de data center que permitiu a solução escalável MLPerf da Habana.





































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)