CUDA, ROCM, eine API? — Ausführen von Code auf einer GPU, einer beliebigen GPU
Warum ist es ein notwendiges Übel, das GPU-Programmiermodell mehrerer Anbieter zu kennen … oder doch nicht?
Einführung
In meinen letzten beiden Posts über Parallel- und Beschleunigerprogrammierung habe ich über die Grundlagen der Beschleuniger- und Parallelprogrammierung und einige Programmierkonzepte gesprochen, die erforderlich sind, um die Korrektheit Ihres Codes sicherzustellen. Die interessante Frage für Programmierer, die die Beschleunigerprogrammierung lernen, lautet: „Muss ich wirklich CUDA, ROCm und SYCL lernen, um für NVIDIA-, AMD- und Intel-Beschleuniger zu programmieren?“
Bei der Planung dieser Serie hatte ich erwartet, in die Ähnlichkeiten und Unterschiede zwischen der Hardwareausführung und den Speichermodellen jeder Architektur einzutauchen. Ich wollte über Warps, Wavefronts und Arbeitsgruppen sprechen, die jeweiligen Konstrukte, die CUDA, ROCm und SYCL verwenden, um die Ausführung auf Hardware-Threads zu gruppieren. Je mehr ich jedoch darüber nachdenke, desto mehr erscheint mir das ein wenig zu viel für einen Blogbeitrag. Wenn Sie an diesen Themen interessiert sind, sehen Sie sich das nette SYCL für CUDA-Entwickler von Codeplay an.
Stattdessen werde ich mich heute darauf konzentrieren, wie Sie so schnell wie möglich von keinem Code zur Ausführung auf einer GPU, einer beliebigen GPU, gelangen. Nichts macht so viel Spaß, wie die Leistungsvorteile Ihres Beschleunigers so schnell wie möglich zu sehen. Für mich macht das Spaß, weil es mit der Veröffentlichung von Codeplay oneAPI für NVIDIA und oneAPI für AMD (Beta) zusammenfällt .
SYCL und GPUs mehrerer Anbieter
SYCL ist ein Programmiermodell, das Compiler-Unterstützung für NVIDIA-, AMD- und Intel-GPUs bietet. Sie können Ihren Code in SYCL schreiben und ihn dann auf den GPUs dieser Anbieter erstellen und ausführen. Bisher erforderte dies je nach GPU-Ziel die Verwendung verschiedener Community-Compiler oder das Erstellen des Intel Open Source-Compilers. Mit der Veröffentlichung der neuesten Codeplay-Toolchains können Sie Ihren Code jetzt schnell und einfach über eine einzige, vorgefertigte Toolchain zum Laufen bringen. Weitere Einzelheiten hierzu finden Sie im Blog von Ruyman Reyes, CTO von Codeplay, zu ihrer neuen Version.
Eine Frage, die Sie sich vielleicht stellen, ist, kann ich meinen Code tatsächlich einmal erstellen und dann zur Laufzeit entscheiden, auf welcher GPU ausgeführt werden soll? Die Antwort ist JA ! Das ist das Schöne an dieser Unterstützung, Sie erstellen Ihren Code einmal und zur Laufzeit können Sie Ihr Ziel manuell auswählen oder die Laufzeitbibliothek automatisch für Sie auswählen lassen.
Da Sie so weit gekommen sind, gehe ich davon aus, dass dies für Sie von Interesse ist, und mein Ziel ist es, Sie auf der GPU Ihrer Wahl zum Laufen zu bringen. Für meine Zwecke teste ich alle 3 Anbieter-GPUs auf Ubuntu 22.04 und installiere über APT.
Installieren der Codeplay-Toolchain
Zuerst richten wir einige grundlegende Systempakete ein:
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
Stellen Sie sicher, dass Sie die Basistreiber / Frameworks haben, die Sie für jede GPU benötigen / die Sie anvisieren möchten. Auch hier verlinke ich die Ubuntu-Anweisungen:
Installieren Sie den Intel GPU-Treiber
Anweisungen für Intel-GPUs auf verschiedenen Betriebssystemen finden Sie hier . Da ich einen Intel Arc unter Ubuntu 22.04 verwende, habe ich diese Anweisungen befolgt .
oneAPI für NVIDIA-Installation
Sie können hier gehen , um die neuesten offiziellen Anweisungen zur Installation von CUDA zu erhalten. Ich füge ein, was ich verwende, um es zum Laufen zu bringen:
- Installieren Sie CUDA keyring, CUDA und starten Sie neu
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}}
Sie können hier gehen , um die neuesten offiziellen Anweisungen zur Installation von ROCm zu erhalten, wieder hier eingefügt, um die Dinge für Sie ein wenig einfacher zu machen:
- Installieren Sie das AMD amdgpu-install-Programm über 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
Es gibt viele verschiedene Codebeispiele, die Sie im Open-Source-oneAPI-Beispiele-GitHub-Repository ausprobieren können:
Aus dem Codeplay-Beispiel können Sie sehen, dass sie diese simple-sycl-app.cpp erstellt haben:
#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;
}
Um für unsere verschiedenen Ziele zu bauen, könnten wir normalerweise Befehlszeilen verwenden, die wie folgt aussehen:
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
Erstellen für GPUs mehrerer Anbieter
Nehmen wir an, ich wollte gleichzeitig für NVIDIA- und Intel-GPUs laufen, ich kann tatsächlich eine fette Binärdatei erstellen, die entweder auf einer NVIDIA- oder Intel-GPU läuft. Der Trick besteht darin, Ihre Build-Befehlszeilenparameter so einzustellen, dass sie mehrere SYCL-Ziele haben.
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!
Zukünftige Arbeit
Einigen aufmerksamen Lesern wird vielleicht auffallen, dass ich kein AMD-Beispiel in mein Multivendor-GPU-Beispiel aufgenommen habe. Dies liegt daran, dass ich kürzlich die AMD 6800XT-GPU durch eine brandneue AMD RX 7900XT-GPU ersetzt habe. Leider wird ROCm derzeit nicht richtig auf meinem Linux-System installiert, unabhängig vom Kernel, den ich mit der RDNA3-Karte verwende. Sobald dies aktualisiert ist, werde ich zurückkommen und Anweisungen mit einem Beispiel geben, das auf allen 3 Karten ausgeführt wird.
Beachten Sie, dass früher eine Version dieses Flows für den 6800XT funktionierte, aber das war, bevor die Codeplay-Software mit dem hier dokumentierten Open-Source-DPC++-Flow veröffentlicht wurde:
Fazit
Mit der oneAPI für NVIDIA-GPUs von Codeplay konnte ich ganz einfach Binärdateien für NVIDIA- oder Intel-GPUs erstellen. Die Zeit für die Einrichtung der zusätzlichen oneAPI für NVIDIA-GPUs betrug etwa 10 Minuten zusätzlich zu der Zeit für die Installation des Intel oneAPI Base Toolkits. Dazu gehörte die Installation von CUDA und der Codeplay-Software.
Die neue Codeplay-Software erschließt eine brandneue Option für Einzelpersonen und Unternehmen, die GPU-Optionen mehrerer Anbieter in Betracht ziehen. Vorher waren die Optionen Open-Source-Compiler, die von der Community unterstützt wurden. Dies ist eine fantastische Option und das, was ich normalerweise für die tägliche Arbeit verwende.
Für Menschen, die einen längerfristigen Support in Betracht ziehen, alias Unternehmen, die sich für ihren Lebensunterhalt auf Toolchains verlassen, kann eine offiziell unterstützte Option von Codeplay und Intel helfen, sich zu beruhigen.
Wenn Sie sehen möchten, welche zufälligen Tech-News ich lese, können Sie mir auf Twitter folgen . Sehen Sie sich auch Code Together an, einen Intel-Podcast für Entwickler, den ich hoste und in dem wir über Technik sprechen.
Tony ist Softwarearchitekt und technischer Evangelist bei Intel. Er war Architekt von Intel VTune Profiler und anderen Performance-Tools und leitete zuletzt das Software-Engineering-Team, das die Rechenzentrumsplattform aufbaute, die Habanas skalierbare MLPerf-Lösung ermöglichte.

![Was ist überhaupt eine verknüpfte Liste? [Teil 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































