CUDA, ROCm, oneAPI? — รันโค้ดบน GPU, GPU ใดๆ
เหตุใดการรู้รูปแบบการเขียนโปรแกรม GPU ของผู้จำหน่ายหลายรายจึงเป็นสิ่งที่ชั่วร้ายที่จำเป็น...ใช่หรือไม่?
บทนำ
ในสองโพสต์ ล่าสุดของฉัน เกี่ยวกับการเขียนโปรแกรมแบบขนานและตัวเร่งความเร็ว ฉันได้พูดคุยเกี่ยวกับพื้นฐานของการเขียนโปรแกรมตัวเร่งความเร็วและแบบขนาน และแนวคิดการเขียนโปรแกรมบางอย่างที่จำเป็นเพื่อให้แน่ใจว่าโค้ดของคุณถูกต้อง คำถามที่น่าสนใจสำหรับการเขียนโปรแกรมเร่งการเรียนรู้ของโปรแกรมเมอร์คือ “ฉันจำเป็นต้องเรียนรู้ CUDA, ROCm และ SYCL เพื่อเขียนโปรแกรมสำหรับ NVIDIA, AMD และ Intel accelerators หรือไม่”
เมื่อวางแผนซีรีส์นี้ ฉันคาดหวังที่จะเจาะลึกถึงความเหมือนและความแตกต่างระหว่างการทำงานของฮาร์ดแวร์และโมเดลหน่วยความจำของแต่ละสถาปัตยกรรม ฉันกำลังจะพูดถึง warps, wavefronts และ workgroups โครงสร้าง CUDA, ROCm และ SYCL ตามลำดับใช้เพื่อจัดกลุ่มการประมวลผลบนเธรดฮาร์ดแวร์ อย่างไรก็ตาม ยิ่งฉันคิดถึงมันมากเท่าไหร่ ก็ยิ่งดูเหมือนมากเกินไปสำหรับบล็อกโพสต์ หากคุณสนใจหัวข้อเหล่านั้น โปรดดูSYCL ที่ดีสำหรับนักพัฒนา CUDAจาก Codeplay
แต่วันนี้ฉันจะมุ่งเน้นไปที่วิธีทำให้คุณไม่ต้องเขียนโค้ด ไปจนถึงทำงานบน GPU หรือ GPU ใดๆ ก็ได้โดยเร็วที่สุด ไม่มีอะไรสนุกเท่ากับการได้เห็นประโยชน์ของคันเร่งของคุณโดยเร็วที่สุด สำหรับผม มันเป็นเรื่องสนุกเพราะมันเกิดขึ้นพร้อมกับการเปิดตัว Codeplay oneAPI สำหรับ NVIDIAและoneAPI สำหรับ AMD (เบต้า )
SYCL และ GPU ของผู้จำหน่ายหลายราย
SYCL เป็นรูปแบบการเขียนโปรแกรมที่รองรับคอมไพเลอร์สำหรับ GPU NVIDIA, AMD และ Intel คุณสามารถเขียนโค้ดของคุณใน SYCL จากนั้นสร้างและเรียกใช้บน GPU ของผู้จำหน่ายเหล่านั้น ก่อนหน้านี้จำเป็นต้องใช้คอมไพเลอร์ชุมชนต่างๆ หรือสร้างคอมไพเลอร์ Intel Open Source ขึ้นอยู่กับเป้าหมาย GPU ของคุณ ด้วยการเปิดตัว Codeplay toolchains ล่าสุด ตอนนี้คุณสามารถเรียกใช้โค้ดของคุณผ่าน toolchain เดียวที่สร้างไว้ล่วงหน้าได้อย่างรวดเร็วและง่ายดาย สำหรับรายละเอียดเพิ่มเติมเกี่ยวกับเรื่องนี้ คุณสามารถอ่าน Ruyman Reyes, CTO ของ Codeplay, บล็อกเกี่ยวกับการเปิดตัวใหม่ของพวกเขา
คำถามหนึ่งที่คุณอาจถามคือฉันจะสร้างโค้ดของฉันเพียงครั้งเดียวจริง ๆ แล้วตัดสินใจว่าจะใช้ GPU ใดในรันไทม์ได้หรือไม่ คำตอบคือใช่ ! นี่คือข้อดีเกี่ยวกับการสนับสนุนนี้ คุณสร้างโค้ดของคุณเพียงครั้งเดียวและในขณะรันไทม์ คุณสามารถเลือกเป้าหมายด้วยตนเอง หรือปล่อยให้ไลบรารีรันไทม์เลือกให้คุณโดยอัตโนมัติ
เนื่องจากคุณมาไกลขนาดนี้แล้ว ฉันจะถือว่าสิ่งนี้เป็นที่สนใจของคุณ และเป้าหมายของฉันคือช่วยให้คุณเริ่มต้นใช้งาน GPU ที่คุณเลือกได้ สำหรับจุดประสงค์ของฉัน ฉันกำลังทดสอบ GPU ของผู้จำหน่ายทั้ง 3 รายบน Ubuntu 22.04 และทำการติดตั้งผ่าน APT
การติดตั้ง Codeplay toolchain
อันดับแรก เราตั้งค่าแพ็คเกจระบบพื้นฐานบางอย่าง:
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 อีกครั้ง:
ติดตั้งไดรเวอร์ Intel GPU
สามารถดูคำแนะนำสำหรับ Intel GPUs บน OS ต่างๆ ได้ที่นี่ เนื่องจากฉันใช้ Intel Arc บน Ubuntu 22.04 ฉันจึงทำตามคำแนะนำ เหล่า นี้
oneAPI สำหรับการติดตั้ง NVIDIA
คุณสามารถไปที่นี่เพื่อรับคำแนะนำอย่างเป็นทางการล่าสุดเกี่ยวกับวิธีติดตั้ง 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 ได้ที่นี่ เพื่อให้คุณทำสิ่งต่างๆ ได้ง่ายขึ้น:
- ติดตั้งโปรแกรม AMD amdgpu-install ผ่าน 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
มีตัวอย่างโค้ดต่างๆ มากมายที่คุณสามารถลองใช้ในโอเพ่นซอร์ส ตัวอย่างที่เก็บ GitHub ของ oneAPI:
จากตัวอย่าง 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;
}
โดยปกติแล้ว ในการสร้างสำหรับเป้าหมายต่างๆ ของเรา เราสามารถใช้บรรทัดคำสั่งที่มีลักษณะดังนี้:
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
สร้างสำหรับ GPU ของผู้จำหน่ายหลายราย
สมมติว่าฉันต้องการรัน NVIDIA และ Intel GPUs ในเวลาเดียวกัน ฉันสามารถสร้าง fat binary ที่จะรันบน NVIDIA หรือ Intel GPU ได้ เคล็ดลับที่นี่คือการตั้งค่าพารามิเตอร์บรรทัดคำสั่ง build ของคุณอย่างเหมาะสมเพื่อให้มีเป้าหมาย 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!
งานในอนาคต
ผู้อ่านที่ชาญฉลาดบางคนอาจสังเกตเห็นว่าฉันไม่ได้ใส่ตัวอย่าง AMD ในตัวอย่าง GPU ของผู้จำหน่ายหลายราย นี่เป็นเพราะฉันเพิ่งแทนที่ด้วย AMD 6800XT GPU ด้วย AMD RX 7900XT GPU ใหม่ล่าสุด ขออภัย ขณะนี้ ROCm ไม่ได้ติดตั้งอย่างถูกต้องบนระบบ Linux ของฉัน โดยไม่คำนึงถึงเคอร์เนลที่ฉันใช้กับการ์ด RDNA3 เมื่ออัปเดตแล้ว ฉันจะกลับมาและให้คำแนะนำพร้อมตัวอย่างการทำงานบนการ์ดทั้ง 3 ใบ
โปรดทราบว่าก่อนหน้านี้เวอร์ชันของโฟลว์นี้ใช้งานได้กับ 6800XT แต่นั่นคือก่อนที่ซอฟต์แวร์ Codeplay จะเปิดตัวโดยใช้โฟลว์ DPC++ แบบโอเพ่นซอร์สที่บันทึกไว้ที่นี่:
บทสรุป
oneAPI สำหรับ NVIDIA GPUs จาก Codeplay ทำให้ฉันสามารถสร้างไบนารีสำหรับ NVIDIA หรือ Intel GPUs ได้อย่างง่ายดาย เวลาในการตั้งค่า oneAPI เพิ่มเติมสำหรับ NVIDIA GPUs ใช้เวลาประมาณ 10 นาทีในการติดตั้ง Intel oneAPI Base Toolkit ซึ่งรวมถึงการติดตั้ง CUDA และซอฟต์แวร์ Codeplay
ซอฟต์แวร์ Codeplay ใหม่จะปลดล็อกตัวเลือกใหม่ล่าสุดสำหรับบุคคลและบริษัทที่พิจารณาตัวเลือก GPU ของผู้จำหน่ายหลายราย ก่อนที่ตัวเลือกจะเป็นโอเพ่นซอร์ส คอมไพเลอร์ที่สนับสนุนโดยชุมชน นี่เป็นตัวเลือกที่ยอดเยี่ยมและเป็นสิ่งที่ฉันมักใช้กับงานประจำวัน
อย่างไรก็ตาม สำหรับคนที่พิจารณาการสนับสนุนในระยะยาว ธุรกิจต่าง ๆ ต้องพึ่งพา toolchains สำหรับการดำรงชีวิต การมีตัวเลือกที่ได้รับการสนับสนุนอย่างเป็นทางการจาก Codeplay และ Intel สามารถช่วยให้สบายใจได้
ถ้าคุณต้องการดูข่าวเทคโนโลยีแบบสุ่มที่ฉันอ่าน คุณสามารถติดตามฉันได้ที่ Twitter นอกจากนี้ ลองดูCode Togetherซึ่งเป็นพอดคาสต์ของ Intel สำหรับนักพัฒนาที่ฉันโฮสต์ไว้เพื่อพูดคุยเรื่องเทคโนโลยี
Tony เป็นสถาปนิกซอฟต์แวร์และผู้เผยแพร่ศาสนาด้านเทคนิคที่ Intel เขาเป็นสถาปนิกของ Intel VTune Profiler และเครื่องมือประสิทธิภาพอื่นๆ และล่าสุดเป็นผู้นำทีมวิศวกรรมซอฟต์แวร์ที่สร้างแพลตฟอร์มศูนย์ข้อมูลซึ่งเปิดใช้งานโซลูชัน MLPerf ที่ปรับขนาดได้ของ Habana





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)