راه اندازی کودا (CUDA) در داکر (DOCKER)

در این مقاله قصد داریم توضیح بدیم که CUDA چیه و چه قابلیتی رو برای ما فراهم کرده که در ابتدا توضیحات مختصری در مورد CPU , GPU و تفاوت اونا میگیم در ادامه کودا رو مورد برررسی قرار میدیم تعریفش میکنیم در مورد مباحثی که برای خیلی ها اشتباه ایجاد میکنه پیرامون کودا و در نهایت هم که بخش عملی این پست هستش کانفیگ یک سرور لینوکسی برای استفاده از GPU تحت داکر رو انجام میدیم که با نصب درایور انویدیا و توضیحات شروع میشه و در نهایت کانتینر تنسرفلو رو ران میکنیم و تستش میکنیم که ایا از GPU استفاده میکنه یا نه.

سی پی یو CPU

پردازنده، واحد پردازش مرکزی کامپیوتر است که اجرای تمام دستورالعمل‌ها رو مدیریت می‌کنه و اغلب به اون مغز کامپیوتر میگن.

جی پی یو GPU

پردازنده گرافیکی یا Graphic Processor Unit که به اختصار GPU گفته می شه، قطعه ای است که روی کارت های گرافیک و همچنین گرافیک های آنبورد قرار داده می شه. این قطعه به صورت مجزا از CPU کار پردازش و رندرینگ تصاویر رو انجام می ده. کارت گرافیک اطلاعات رو برای پردازش تصویر ترجمه می‌کنه و خروجی رو روی صفحه نمایش نمایش میده. هر چی کارت گرافیک در نمایش تصویر سریعتر باشد، خروجی بصری بهتری داریم.

تفاوت اصلی CPU و GPU

نکته ای که در مورد این تفاوت باید در نظر داشته باشیم و خیلی ها درباره اون اشتباه میکنن، نحوه کار و دستوراتی هست که اجرا می‌شه. در واقع CPU به ازای هر هسته تو هر کلاک می‌تونه یک دستور متفاوت انجام بده در نتیجه یک CPU با ۴ هسته در هر کلاک ۴ تا دستور که می‌تونن کاملا بی‌ربط به هم باشن رو انجام می‌ده. اما در GPU تو هر کلاک تعداد محدودی دستور روی حجم بزرگی از داده بخش بندی شده اجرا می‌شه. به طور مثال همه ۲۵۶۰ هسته یک GTX1080 در هر کلاک فقط یک یا چند دستور محدود رو می‌تونن اجرا کنن اما هر کدوم دارن اون دستور رو روی بخشی از داده‌ها اجرا می‌کنن. یک تفاوت مهم دیگه اینکه تعداد دستورات در GPU نسبت به CPU خیلی کمتره و فقط برای محاسبات ریاضی مناسبه اما CPU توانایی انجام عملیات خیلی گسترده‌تری داره.

کودا CUDA

طبق توضیحات انویدیا CUDA در واقع یک پلتفرم پردازش موازی و مدل برنامه نویسی هستش که توسط انویدیا ساخته شده .

تعریف CUDA رو میشه به دو قسمت تقسیم کرد که قسمت اول میشه Parallel Computing Platform و قسمت دوم Programming Model.

کودا در واقع سرواژه Compute Unified Device Architecture هستش که همونطور که از تعریفش مشخصه یک معماری ای هستش که این قابلیت رو به GPU میده که پردازش های سنگین رو خیلی سریع و همزمان اجرا کند.

توضیحات بیشتر در مورد قسمت دوم تعریف در ادامه میشه.


کانفیگ سرور لینوکسی از صفر برای استفاده از GPU

نصب NVIDIA-Driver

برای استفاده از جی پی یو در هر سیستم عامل و به هر شکلی قطعا نیاز به نصب بودن درایور انویدیا متناسب با سیستم عامل میزبان هستش.

نصب انویدیا درایور ۶ مرحله داره که در زیر هر مرحله رو جداگونه بررسی میکنیم.

1- بررسی اینکه GPU کودا (CUDA) رو ساپورت میکنه یا نه

lspci | grep -i nvidia

دستور lspci یک ابزار کاربردی در سیستم‌های لینوکس است که برای یافتن اطلاعات مربوط به گذرگاه‌های PCI و دستگاه‌های متصل به زیرسیستم PCI استفاده میشه.

در ادامه باید مدل GPU رو داخل سایت زیر بررسی کرد برای پشتیبانی CUDA

https://developer.nvidia.com/cuda-gpus

2-بررسی اینکه ورژن استانداردی از لینوکس نصب هست یا نه

uname -m && cat /etc/&release

3-بررسی اینکه system build tools هایی مانند GCC نصب هست یا نه

gcc --version

4-بررسی اینکه سیستم linux header مناسبی داره یا نه و نصب آن ها

uname -r

#Install linux headers
sudo apt-get install linux-headers-$(uname -r)

5-انتخاب NVIDIA-DRIVER مناسب برای سیستم عامل

#first way
ubuntu-drivers devices
#second way
apt search nvidia-driver

6-نصب درایور

#install driver
sudo apt install nvidia-drver-515-server
#reboot system
sudo reboot

بعد از نصب درایور متناسب با سیستم عامل اگر نصب با موفقیت انجام شده باشه با استفاده از دستور nvidia-smi که همراه درایور نصب میشه روی سیستم میتونیم چک کنیم.

کاربرد NVIDIA-SMI

اینترفیس مدیریت سیستم های انویدیا NVIDIA (NVIDIA-SMI) یک ابزار خط فرمانه که بر پایه کتابخانه مدیریت NVIDIA (NVML) ساخته شده که برای کمک به مدیریت و نظارت به دستگاه های گرافیکی NVIDIA طراحی شده .

کاربرد NVML

یک API نوشته شده با زبان C هستش که برای نظارت و مدیریت وضعیت‌های مختلف دستگاه‌های GPU NVIDIA نوشته شده که امکان دسترسی مستقیم به پرس و جوها و دستورات خروجی از طریق NVIDIA-SMI رو فراهم می کنه.


کودا تولکیت(CUDA TOOLKIT)

کودا تولکیت (CUDA TOOLKIT)توسط انویدیا معرفی شد و هر چیزی که برای توسعه برنامه های GPU مورد نیاز هست رو داخل خودش داره مثل کامپایلرهای مناسب برای برنامه های CUDA ,کتابخونه های مختلف مناسب برای برنامه های جی پی یو , IDES , دیباگر و CUDA RUNTIME .

با نصب nvidia-driver دیگه نیازی به نصب درایور cuda روی سرور نیست بخاطر اینکه cuda driver همراه درایور انویدیا نصب میشوه و ورژن آن هم بعد از چک کردن دستور nvidia-smi مشخص هستش.

دقت کنید که تا به اینجا ما یک سرور لینوکسی ابونتو داریم که فقط انویدیا درایور رو روی اون نصب کردیم که همراه اون درایور کودا هم نصب شده اما هنوز کودا تولکیت که بالاتر توضیح دادیم رو نصب نکردیم.

کاربرد NVCC

در واقع nvcc کامپایلر انویدیا کودا هستش و اگر کودا تولکیت روی سیستم ما نصب باشه میتونیم با استفاده از دستور nvcc –version چک کنیم.

تعریف CUDNN

این کتابخونه برای کار های شبکه های عصبی عمیق با استفاده از GPU استفاده میشه و میشه ازش در چارچوب‌های یادگیری ماشینی پیشرفته، مانند TensorFlow Google، PyTorch و غیره استفاده کرد.

تفاوت CUDA DRIVER LIBRARY و CUDA RUNTIME LIBRARY

کتابخانه CUDA (درایور): با درایور NVIDIA نصب شده و برای برنامه نویسی سطح پایین CUDA در نظر گرفته شده.

shared library name : libcuda.so
header file : cuda.h

کتابخانه CUDA (Runtime): کتابخانه CUDA Runtime با NVIDIA CUDA Toolkit نصب شده است و برای برنامه نویسی CUDA سطح بالا در نظر گرفته شده.

shared library name : libcudart.so
header file : cuda_runtime.h

در حالی که CUDA Driver API و Runtime API عملکردهای مشترکی دارند، در بیشتر سناریوها، استفاده از CUDA Runtime API برای حل مشکل کافیه و کد بسیار ساده‌تر هستش.


استفاده از GPU تحت داکر(DOCKER)

برای استفاده از GPU تحت داکر فقط نیاز به نصب NVIDIA-DRIVER و NVIDIA CONTAINER RUNTIME هست, هیچ نیازی به نصب CUDA TOOLKIT نیستش.

برای اجرای کانتینر های داکری طوری که بتونن از GPU استفاده کننن از فلگ GPUS --ALL استفاده میکنیم و برای اینکار حتما باید NVIDIA CONTAINER RUNTIME نصب باشه.

به نسخه Docker خود با docker -v توجه کنید. نسخه های قبل از 19.03 به nvidia-docker2 و فلگ runtime=nvidia نیاز دارن. در نسخه های بعد از 19.03، از بسته nvidia-container-toolkit و فلگ GPUS --ALL.

کاربرد NVIDIA-CONTAINER-RUNTIME

یک کانتینر رانتایم اگاه از وجود GPU هستش که کاملا با OCI های مورد استفاده از در داکر و بقیه کانتینر انجین ها سازگار هستش که کار ساختن برنامه های GPU با استفاده از داکر رو راحت تر میکنه


اجرا و تست کانتینر ها

برای استفاده از داکر ایمیج تنسرفلو به شکلی که از GPU بتونه استفاده کنه باید ۳ تا مورد روی سیستم هاست نصب باشه

  • انویدیا درایور
  • داکر
  • انویدیا داکر ساپورت

نصب انویدیا ساپورت برای داکر (nvidia-docker2/nvidia-container-runtime)

distribution=$(. /etc/os-release;echo $ID$VERSION_ID) \
&& curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-docker2
sudo systemctl restart docker


تست دسترسی به GPU با استفاده از دستور NVIDIA-SMI از داخل کانتینر انویدیا کودا

sudo docker run --rm --gpus all nvidia/cuda:11.7.0-base-ubuntu22.04 nvidia-smi

دقت کنید که فلگ GPUS --ALL اگر انویدیا داکر ساپورت روی سیستم هاست نصب نباشه ارور میدهه و کانتینر اصلا اجرا نمیشود.

نصب و کانفیگ تنسرفلو به کمک داکر و استفاده از GPU:

docker pull tensorflow/tensorflow:latest-gpu-jupyter
docker run --gpus all -it --rm tensorflow/tensorflow:latest-gpu \
python -c &quotimport tensorflow as tf; print(tf.reduce_sum(tf.random.normal([1000, 1000])))&quot

بررسی اینکه آیا کانتینر تنسرفلو به GPU دسترسی داره یا نه:

tf.config.list_physical_devices('GPU')
gpu_available = tf.test.is_gpu_available()
is_cuda_gpu_available = tf.test.is_gpu_available(cuda_only=True) 
is_cuda_gpu_min = tf.test.is_gpu_available(True, (3,0))