CUDA
معماری یکپارچه محاسباتی دستگاه (CUDA) یک پلتفرم پردازش موازی و مدل رابط برنامهنویسی کاربرد (API) است که توسط NVIDIA ساخته شده است. این فناوری معمولاً برای شتاببخشی به مسائل با محاسبات سنگین استفاده میشود و بهطور گسترده در برنامههای کاربردی رایانش با کارایی بالا (HPC) و یادگیری ماشین (ML) به کار گرفته شده است.
راهنمای کاربر
بستههای ارائهشده توسط NVIDIA که به CUDA نیاز دارند، معمولاً در مجموعههای بستهی CUDA ذخیره میشوند.
Nixpkgs تعدادی مجموعه بستهی CUDA ارائه میدهد که هرکدام بر اساس یک انتشار متفاوت CUDA هستند. صفات (attribute) سطح بالا که دسترسی به مجموعههای بستهی CUDA را فراهم میکنند، از این قراردادهای نامگذاری پیروی میکنند:
cudaPackages_x_y: یک مجموعه بستهی دارای نسخه اصلی-فرعی برای یک انتشار خاص CUDA، که در آنxوyنسخههای اصلی و فرعی آن انتشار CUDA هستند.cudaPackages_x: یک نام مستعار دارای نسخه اصلی به مجموعه بستهی CUDA دارای نسخه اصلی-فرعی با آخرین انتشار اصلی CUDA که بهطور گسترده پشتیبانی میشود.cudaPackages: یک نام مستعار بدون نسخه به نام مستعار دارای نسخه اصلی برای آخرین انتشار CUDA که بهطور گسترده پشتیبانی میشود. مجموعه بستهای که توسط این نام مستعار ارجاع داده میشود، مجموعه بستهی CUDA «پیشفرض» نیز نامیده میشود.
توصیه میشود از صفت (attribute) بدون نسخه cudaPackages استفاده کنید. اگرچه مجموعههای بستهی دارای نسخه (مانند cudaPackages_12_8) در دسترس هستند، اما به صورت دورهای حذف میشوند.
در ادامه دو مثال برای روشن شدن قراردادهای نامگذاری آورده شده است:
- اگر
cudaPackages_12_9آخرین انتشار در سری 12.x باشد، اما کتابخانههای اصلی مانند OpenCV یا ONNX Runtime در ساخت با آن شکست بخورند،cudaPackages_12ممکن است به جایcudaPackages_12_9نام مستعاری برایcudaPackages_12_8باشد. - اگر
cudaPackages_13_1آخرین انتشار باشد، اما کتابخانههای اصلی مانند PyTorch یا Torch Vision در ساخت با آن شکست بخورند،cudaPackagesممکن است به جایcudaPackages_13نام مستعاری برایcudaPackages_12باشد.
تمام مجموعههای بستهی CUDA شامل بستههای رایج CUDA مانند libcublas، cudnn، tensorrt و nccl هستند.
پیکربندی Nixpkgs برای CUDA
پشتیبانی از CUDA به صورت پیشفرض در Nixpkgs فعال نیست. برای فعالسازی پشتیبانی CUDA، اطمینان حاصل کنید که Nixpkgs با یک پیکربندی مشابه زیر درونریزی میشود:
{ pkgs }:
{
allowUnfreePredicate = pkgs._cuda.lib.allowUnfreeCudaPredicate;
cudaCapabilities = [ <target-architectures> ];
cudaForwardCompat = true;
cudaSupport = true;
} اکثریت بستههای CUDA غیرآزاد (unfree) هستند، بنابراین باید یا allowUnfreePredicate یا allowUnfree تنظیم شود.
گزینه پیکربندی cudaSupport توسط بستهها برای فعالسازی شرطی قابلیتهای مخصوص CUDA استفاده میشود. این گزینه پیکربندی معمولاً توسط بستههایی استفاده میشود که میتوانند با یا بدون پشتیبانی از CUDA ساخت (Build) شوند.
گزینه پیکربندی cudaCapabilities فهرستی از قابلیتهای CUDA را مشخص میکند. بستهها ممکن است از این گزینه برای کنترل تولید کد دستگاه استفاده کنند تا از قابلیتهای مخصوص معماری بهرهمند شوند، زمانهای کامپایل را با تولید کد کمتر برای دستگاه سرعت بخشند، یا حجم closure بستهها را کاهش دهند. به عنوان مثال، میتوانید برای پردازندههای گرافیکی Ada Lovelace با cudaCapabilities = [ "8.9" ]; اقدام به ساخت کنید. اگر cudaCapabilities ارائه نشود، مقدار پیشفرض بهازای هر مجموعه بسته محاسبه میشود که از فهرست پردازندههای گرافیکی پشتیبانیشده توسط آن نسخه CUDA بهدست میآید. لطفاً برای کارتهای خاص به supported GPUs مراجعه کنید. نگهدارندگان کتابخانه باید به NVCC Docs و یادداشتهای انتشار آن مراجعه کنند.
احتیاط
برخی از قابلیتهای CUDA به طور پیشفرض هدفگیری نمیشوند، از جمله قابلیتهای متعلق به خانواده دستگاههای Jetson (به عنوان مثال
8.7که مربوط به Jetson Orin است) یا مجموعهویژگیهای غیر پایه (به عنوان مثال9.0aکه مربوط به مجموعه ویژگیهای اختصاصی Hopper است). اگر نیاز دارید این قابلیتها را هدفگیری کنید، باید به صراحتcudaCapabilitiesرا طوری تنظیم کنید که آنها را شامل شود.
گزینه پیکربندی بولین cudaForwardCompat تعیین میکند که آیا پشتیبانی PTX برای سختافزارهای آینده فعال است یا خیر.
تغییر مجموعههای بسته CUDA
مجموعههای بسته CUDA در pkgs/top-level/cuda-packages.nix تعریف شدهاند. یک مجموعه بسته CUDA با فراخوانی callPackage روی pkgs/development/cuda-modules/default.nix همراه با یک مجموعه ویژگی به نام manifests ایجاد میشود که شامل مانیفستهای NVIDIA برای هر فایل قابل توزیع مجدد است. مانیفستهای مربوط به موارد قابل توزیع مجددِ پشتیبانیشده از طریق _cuda.manifests در دسترس هستند و در مسیر pkgs/development/cuda-modules/_cuda/manifests قرار دارند.
اکثریت ابزارهای مجموعه بسته CUDA از طریق مجموعه ویژگی سطح بالای _cuda در دسترس هستند، که یک نقطه ثابت (fixed-point) تعریفشده در خارج از مجموعههای بسته CUDA است. به عنوان یک نقطه ثابت، _cuda باید از طریق صفت extend خود تغییر داده شود.
احتیاط
همانطور که از پیشوند خط زیرین مشخص است،
_cudaجزئیات پیادهسازی است و هیچ تضمینی در رابطه با پایداری یا API آن ارائه نمیشود. مجموعه ویژگی_cudaصرفاً برای تسهیل ایجاد یا تغییر مجموعههای بسته CUDA توسط کاربران متخصص خارج از درخت (out-of-tree) ارائه شده است.
تغییرات خارج از درخت بستهها باید از overrideAttrs برای اعمال هرگونه تغییر لازم در عبارت بسته استفاده کنند.
نکته
مجموعه ویژگی
_cudaقبلاًfixupsرا ارائه میداد، که یک مجموعه ویژگی برای نگاشت نام بسته (pname) به یک عبارت سازگار باcallPackageبود و آن را بهoverrideAttrsروی نتیجه یک سازنده (builder) عمومی قابل توزیع مجدد ارائه میداد. این قابلیت به نفع گنجاندن عبارتهای کامل بسته برای هر بسته قابل توزیع مجدد حذف شده است تا از عضویت سازگار در مجموعه ویژگی در سراسر نسخهها، پلتفرمها و پیکربندیهای پشتیبانیشده CUDA اطمینان حاصل شود.
گسترش مجموعههای بسته CUDA
مجموعههای بسته CUDA دارای اسکوپ (scope) هستند و صفت معمول overrideScope را برای بازنشانی صفات بسته ارائه میدهند (یادداشت مربوط به _cuda در پیکربندی مجموعههای بسته CUDA را ببینید).
با الهام از pythonPackagesExtensions، صفت _cuda.extensions فهرستی از افزونهها است که روی تمامی نسخههای مجموعه بستههای CUDA اعمال میشود، و امکان تغییر همهٔ نسخههای مجموعه بستههای CUDA را بدون نیاز به دانستن نام آنها یا شمارش و تغییر صریح آنها فراهم میسازد. بهعنوان مثال، غیرفعال کردن cuda_compat در تمامی مجموعه بستههای CUDA با این اورلی امکانپذیر است:
final: prev: {
_cuda = prev._cuda.extend (
_: prevAttrs: {
extensions = prevAttrs.extensions ++ [ (_: _: { cuda_compat = null; }) ];
}
);
} بستههای قابل توزیع مجدد توسط کمکرسان ساخت buildRedist ساخته میشوند؛ برای مشاهدهی پیادهسازی، pkgs/development/cuda-modules/buildRedist/default.nix را ببینید.
استفاده از cudaPackages
احتیاط
مقدار غیربدیهی از قابلیت کشف و قابلیت استفادهی بستههای CUDA به قلابهای راهاندازی (setup hooks) گوناگونی متکی است که توسط یک مجموعه بستهی CUDA استفاده میشوند. در نتیجه، کاربران احتمالاً هنگام تلاش برای انجام ساختها درون یک
devShellبدون فراخوانی دستی فازها، با مشکل مواجه خواهند شد.
برای استفاده از یک یا چند بسته CUDA در یک عبارت، یک پارامتر cudaPackages به عبارت بدهید و در صورتی که پشتیبانی از CUDA اختیاری باشد، پارامترهای config و cudaSupport را اضافه کنید:
{
config,
cudaSupport ? config.cudaSupport,
cudaPackages,
}:
<package-expression> در آرگومانهای derivation بستهتان، اکیداً توصیه میشود که موارد زیر تنظیم شوند:
{
__structuredAttrs = true;
strictDeps = true;
} این تنظیمات تضمین میکنند که قلابهای راهاندازی CUDA طبق انتظار عمل کنند.
هنگام استفاده از callPackage، میتوانید گونهی دیگری را پاس دهید؛ برای مثال زمانی که یک بسته به نسخه خاصی از CUDA نیاز دارد:
{ mypkg = callPackage { cudaPackages = cudaPackages_12_6; }; } احتیاط
بازنشانی مجموعه بسته CUDA برای یک بسته ممکن است باعث ناسازگاری شود، زیرا این بازنشانی بر وابستگیهای مستقیم یا گذرای آن تأثیری نمیگذارد. در نتیجه، بهسادگی ممکن است بستهای داشته باشید که از مجموعه بسته CUDA متفاوتی نسبت به وابستگیهای خود استفاده میکند. در صورت امکان، توصیه میشود مجموعه بسته CUDA پیشفرض را به صورت سرتاسری تغییر دهید تا از یک محیط سازگار مطمئن شوید.
گونههای CUDA در Nixpkgs
گونههای CUDA در Nixpkgs در درجه اول برای سهولت در انتخاب بستههای دارای پشتیبانی از CUDA بر اساس مسیر صفت ارائه شدهاند. به عنوان مثال، مجموعه گونههای CUDA Nixpkgs در pkgsForCudaArch به شما امکان میدهد با استفاده از مسیر صفت pkgsForCudaArch.sm_89.opencv به نمونهای از OpenCV با پشتیبانی CUDA برای پردازنده گرافیکی Ada Lovelace دسترسی پیدا کنید، بدون اینکه نیازی به تغییر config ارائهشده هنگام درونریزی Nixpkgs داشته باشید.
احتیاط
گونههای Nixpkgs بدون هزینه نیستند: آنها نیاز به ارزیابی مجدد Nixpkgs دارند. در صورت امکان، Nixpkgs را یکبار با پیکربندی دلخواه درونریزی کنید.
استفاده از cudaPackages.pkgs
هر مجموعه بسته CUDA دارای صفت pkgs است که گونهای از Nixpkgs محسوب میشود که در آن مجموعه بسته CUDA دربرگیرنده به پیشفرض تبدیل میشود. این کار عمدتاً برای جلوگیری از نشت مجموعه بسته انجام شده است؛ جایی که یکی از اعضای مجموعه بسته CUDA غیرپیشفرض، وابستگی (احتمالاً گذرایی) به عضوی از مجموعه بسته CUDA پیشفرض داشته باشد.
نکته
نشت مجموعه بسته یک مشکل رایج در Nixpkgs است و به مجموعههای بسته CUDA محدود نمیشود.
به عنوان یک مزیت اضافی برای این نوع پیکربندی pkgs، ساخت یک بسته با نسخهای غیرپیشفرض از CUDA به سادگیِ دسترسی به یک صفت (attribute) است. به عنوان مثال، cudaPackages_12_8.pkgs.opencv بسته OpenCV ساختشده در برابر CUDA 12.8 را ارائه میدهد.
استفاده از pkgsCuda
مجموعه ویژگی pkgsCuda گونهای از Nixpkgs است که با cudaSupport = true; و rocmSupport = false پیکربندی شده است. این روش، راهکاری راحت برای دسترسی به گونهای از Nixpkgs است که با مجموعه قابلیتهای پیشفرض CUDA پیکربندی شده است.
استفاده از pkgsForCudaArch
مجموعه ویژگی pkgsForCudaArch معماریهای CUDA (مانند sm_89 برای Ada Lovelace یا sm_90a برای معماری خاص Hopper) را به گونههای Nixpkgs نگاشت میکند که دقیقاً برای پشتیبانی از همان معماری پیکربندی شدهاند. به عنوان مثال، pkgsForCudaArch.sm_89 گونهای از Nixpkgs است که pkgs را گسترش داده و مقادیر زیر را در config تنظیم میکند:
{
cudaSupport = true;
cudaCapabilities = [ "8.9" ];
cudaForwardCompat = false;
} نکته
در
pkgsForCudaArch، گزینهٔcudaForwardCompatرویfalseتنظیم شده است زیرا واریانت مربوطه در Nixpkgs دقیقاً از یک معماری CUDA پشتیبانی میکند. بهعلاوه، برخی از معماریها، از جمله مجموعهویژگیهای مختص به معماری مانندsm_90a، نمیتوانند با قابلیت سازگاری رو به جلو (forward compatibility) ساخته شوند.
احتیاط
همهٔ نسخههای CUDA از تمامی معماریها پشتیبانی نمیکنند!
برای توضیح بیشتر: پشتیبانی از Blackwell (برای مثال
sm_100) در CUDA 12.8 اضافه شد. فرض کنید مجموعه بستههای پیشفرض CUDA در Nixpkgs ما روی CUDA 12.6 باشد. در این صورت، واریانت Nixpkgs موجود از طریقpkgsForCudaArch.sm_100بیاستفاده خواهد بود، زیرا بستههایی مانندpkgsForCudaArch.sm_100.opencvوpkgsForCudaArch.sm_100.python3Packages.torchتلاش خواهند کرد کدی برایsm_100تولید کنند، معماریای که برای CUDA 12.6 ناشناخته است. در آن صورت، باید در عوض ازpkgsForCudaArch.sm_100.cudaPackages_12_8.pkgsاستفاده کنید (برای جزئیات بیشتر به استفاده ازcudaPackages.pkgsمراجعه کنید).
مجموعه ویژگی pkgsForCudaArch دسترسی به بستههای ساختهشده برای یک معماری خاص را بدون نیاز به فراخوانی دستی pkgs.extend و ارائهٔ یک config جدید امکانپذیر میسازد. به عنوان نمونه، pkgsForCudaArch.sm_89.python3Packages.torch نرمافزار PyTorch ساختهشده برای پردازندههای گرافیکی Ada Lovelace را ارائه میدهد.
اجرای کانتینرهای Docker یا Podman با پشتیبانی از CUDA
امکان اجرای کانتینرهای Docker یا Podman با پشتیبانی از CUDA وجود دارد. سازوکار پیشنهادی برای انجام این کار، استفاده از NVIDIA Container Toolkit است.
ابزار NVIDIA Container Toolkit را میتوان در NixOS به صورت زیر فعال کرد:
{ hardware.nvidia-container-toolkit.enable = true; } این کار بهطور خودکار سرویسی را فعال میکند که بر اساس سختافزار خودکار شناساییشدهی ماشین شما، یک مشخصات CDI (واقع در /var/run/cdi/nvidia-container-toolkit.json) ایجاد میکند. میتوانید این سرویس را با اجرای دستور زیر بررسی کنید:
$ systemctl status nvidia-container-toolkit-cdi-generator.service نکته
بسته به تنظیماتی که قبلاً در سیستم خود فعال کردهاید، ممکن است لازم باشد ماشین خود را راهاندازی مجدد کنید تا NVIDIA Container Toolkit یک مشخصات CDI معتبر برای ماشین شما تولید کند.
هنگامی که یک مشخصات CDI معتبر در زمان راهاندازی (بوت) برای ماشین شما تولید شد، هر دو Podman و Docker (> 25) در صورت ارائهی پرچم --device از این مشخصات استفاده خواهند کرد:
$ podman run --rm -it --device=nvidia.com/gpu=all ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>) $ docker run --rm -it --device=nvidia.com/gpu=all ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>) میتوانید با بررسی محتوای فایل /var/run/cdi/nvidia-container-toolkit.json، تمامی شناسههای ایجادشده برای سختافزارِ به طور خودکار شناساییشدهی خود را بررسی کنید:
$ nix run nixpkgs#jq -- -r '.devices[].name' < /var/run/cdi/nvidia-container-toolkit.json
0
1
all مشخص کردن دستگاههای قابل دسترس برای کنتینر
شما میتوانید با استفاده از شناسه موجود در مشخصات CDI تولیدشده، انتخاب کنید که چه دستگاههایی در معرض کنتینرهای شما قرار گیرند. به صورت زیر:
$ podman run --rm -it --device=nvidia.com/gpu=0 ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>) اگر چندین GPU دارید و میخواهید مشخص کنید کدامیک در دسترس کنتینر قرار گیرند، میتوانید آرگومان --device را به هر تعداد که لازم است تکرار کنید:
$ podman run --rm -it --device=nvidia.com/gpu=0 --device=nvidia.com/gpu=1 ubuntu:latest nvidia-smi -L
GPU 0: NVIDIA GeForce RTX 4090 (UUID: <REDACTED>)
GPU 1: NVIDIA GeForce RTX 2080 SUPER (UUID: <REDACTED>) نکته
بهطور پیشفرض، NVIDIA Container Toolkit از اندیس GPU برای شناسایی دستگاههای مشخص استفاده میکند. شما میتوانید نحوهٔ شناسایی دستگاههایی که قرار است در دسترس قرار گیرند را با استفاده از صفت (attribute) NixOS به نام
hardware.nvidia-container-toolkit.device-name-strategyتغییر دهید.
استفاده از docker-compose
همچنین امکان در دسترس قرار دادن GPUها برای یک محیط docker-compose نیز وجود دارد. با یک فایل docker-compose.yaml مانند زیر:
services:
some-service:
image: ubuntu:latest
command: sleep infinity
deploy:
resources:
reservations:
devices:
- driver: cdi
device_ids:
- nvidia.com/gpu=all به همین ترتیب، میتوانید دستگاههای خاصی را انتخاب کنید که در دسترس کنتینر قرار میگیرند:
services:
some-service:
image: ubuntu:latest
command: sleep infinity
deploy:
resources:
reservations:
devices:
- driver: cdi
device_ids:
- nvidia.com/gpu=0
- nvidia.com/gpu=1 مشارکت
هشدار
این بخش از مستندات هنوز بهشدت در حال تکمیل است. بازخوردها در بخش GitHub Issues با تگ کردن @NixOS/cuda-maintainers یا در Matrix پذیرفته میشود.
نگهداری مجموعهی بستهها
مجموعهابزار CUDA Toolkit مجموعهای از کتابخانهها و نرمافزارهای CUDA است که برای ارائه محیط توسعه جهت برنامههای شتابیافته با CUDA در نظر گرفته شده است. تا پیش از انتشار CUDA 11.4، شرکت NVIDIA مجموعه CUDA Toolkit را تنها به صورت یک نصاب runfile چندگیگابایتی ارائه میکرد. از نسخه CUDA 11.4 به بعد، NVIDIA توزیعپذیرهای CUDA موسوم به («CUDA-redist») را نیز ارائه کرده است: قطعات مستقل بستهبندیشده از CUDA Toolkit که هدف آنها تسهیل بازتوزیع و گنجاندن در پروژههای پاییندستی است. این بستهها در مجموعهی بستههای cudaPackages در دسترس هستند.
اگرچه نصاب یکپارچه runfile برای CUDA Toolkit دیگر ارائه نمیشود، cudaPackages.cudatoolkit یک تقریب پیوندیافته با symlinkJoin از کتابخانههای رایج را ارائه میدهد. استفاده از cudaPackages.cudatoolkit توصیه نمیشود: همه پروژههای جدید باید به جای آن از توزیعپذیرهای CUDA موجود در cudaPackages استفاده کنند، زیرا نگهداری و بهروزرسانی آنها بسیار آسانتر است.
بهروزرسانی توزیعپذیرها
هر زمان که نسخه جدیدی از مانیفست توزیعپذیرها در دسترس قرار گرفت:
- برای آدرس URL مورد استفاده هنگام vendor کردن مانیفستها، فایل README.md مربوطه در
pkgs/development/cuda-modules/_cuda/manifestsرا بررسی کنید. - نسخه مانیفست استفادهشده در ساخت هر مجموعهی بستههای CUDA در
pkgs/top-level/cuda-packages.nixرا بهروزرسانی کنید. - عبارتهای بسته را در
pkgs/development/cuda-modules/packagesبهروزرسانی کنید.
بهروزرسانی عبارتهای بسته شامل موارد زیر است:
- افزودن اصلاحات مشروط به انتشار نسخههای جدیدتر، مانند وابستگیهای اضافه یا حذف شده
- افزودن عبارتهای بسته برای بستههای جدید
- بهروزرسانی
passthru.brokenConditionsوpassthru.badPlatformsConditionsبا محدودیتهای مختلف (به عنوان مثال، نسخههای جدیدی که پشتیبانی از معماریهای مختلف را حذف میکنند)
بهروزرسانی کامپایلرها و پردازندههای گرافیکی پشتیبانیشده
- مقدار
nvccCompatibilitiesدرpkgs/development/cuda-modules/_cuda/db/bootstrap/nvcc.nixرا بهروزرسانی کنید تا شامل جدیدترین نسخه NVCC و همچنین هر کامپایلر هاستِ جدیداً پشتیبانیشده باشد. - مقدار
cudaCapabilityToInfoدرpkgs/development/cuda-modules/_cuda/db/bootstrap/cuda.nixرا بهروزرسانی کنید تا شامل هر GPU جدیدی باشد که توسط نسخه جدید CUDA پشتیبانی میشود.
بهروزرسانی مجموعهی بستههای CUDA
نکته
تغییر مجموعهی بستههای پیشفرض CUDA باید در یک PR جداگانه انجام شود تا زمان کافی برای تستهای اضافی فراهم باشد.
هشدار
همانطور که در استفاده از
cudaPackages.pkgsتوضیح داده شده است، راهکار پیادهسازی فعلی برای نشت مجموعهی بستهها شامل ایجاد یک نمونه جدید برای هر یک از مجموعههای بستههای غیرپیشفرض CUDA است. به همین دلیل، باید تعداد مجموعهبستههای CUDA که مقدارrecurseForDerivationsدر آنها برابر با true است را محدود کنیم:lib.recurseIntoAttrsتنها باید روی مجموعهی بستههای پیشفرض CUDA اعمال شود.
- یک مجموعه بسته جدید
cudaPackages_<major>_<minor>را درpkgs/top-level/cuda-packages.nixقرار داده و آن را درpkgs/top-level/all-packages.nixبه ارث ببرید (inherit کنید). - بستار (closure) مجموعه بسته جدید را با موفقیت بسازید، و عبارتها را در
pkgs/development/cuda-modules/packagesبر حسب نیاز بهروزرسانی کنید. در ادامه برخی از خطاهای رایج آمده است:
| عدم توانایی در ... | در هنگام ... | علت | راه حل | نکته |
|---|---|---|---|---|
| یافتن هدرها | configurePhase یا buildPhase | نبود وابستگی به یک خروجی dev | افزودن وابستگی مفقود | خروجی dev معمولاً شامل هدرها است |
| یافتن کتابخانهها | configurePhase | نبود وابستگی به یک خروجی dev | افزودن وابستگی مفقود | خروجی dev معمولاً شامل فایلهای پیکربندی CMake است |
| یافتن کتابخانهها | buildPhase یا patchelf | نبود وابستگی به یک خروجی lib یا static | افزودن وابستگی مفقود | خروجی lib یا static معمولاً شامل کتابخانهها است |
نکته
دو درایویشن کاربردی، تست بهروزرسانیهای مجموعه بسته را آسانتر میکنند:
cudaPackages.tests.redists-unpacked: مقدارsrcهر بسته قابل توزیع مجدد که از حالت فشرده خارج شده و باsymlinkJoinپیوند یافته استcudaPackages.tests.redists-installed: هر خروجی از هر بسته قابل توزیع مجدد که باsymlinkJoinپیوند یافته است
عدم موفقیت در اجرای باینری حاصل، معمولاً دشوارترین مورد برای دیباگ (اشکالزدایی) است، زیرا ممکن است ترکیبی از مشکلات ذکرشده در بالا باشد. این نوع شکست معمولاً زمانی رخ میدهد که یک کتابخانه تلاش میکند کتابخانهای را که به آن وابسته است اما در بخش DT_NEEDED خود اعلام نکرده، بارگذاری یا باز کند. مراحل دیباگ (اشکالزدایی) زیر را امتحان کنید:
- ابتدا مطمئن شوید که وابستگیها با
autoAddDriverRunpathپچ شدهاند. - در صورت عدم موفقیت، تلاش کنید برنامه را با
nixGLیا یک ابزار پوششدهنده (wrapper) مشابه اجرا کنید. - اگر این کار جواب داد، احتمالاً به این معنی است که برنامه تلاش میکند کتابخانهای را بارگذاری کند که در
RPATHیاRUNPATHباینری وجود ندارد.
نوشتن تستها
احتیاط
وجود
passthru.testersوpassthru.testsباید به عنوان جزئیات پیادهسازی در نظر گرفته شود -- قرار نیست آنها یک رابط عمومی یا پایدار باشند.
به طور کلی، دو مجموعه صفت (attribute set) در passthru وجود دارد که برای ساخت و اجرای تستهای بستههای CUDA استفاده میشوند: passthru.testers و passthru.tests. هر مجموعه صفت ممکن است شامل یک مجموعه صفت به نام cuda باشد که حاوی درایویشنهای مخصوص CUDA است. مجموعه صفت cuda برای جداسازی درایویشنهای مخصوص CUDA از درایویشنهایی استفاده میشود که از پیادهسازیهای متعدد پشتیبانی میکنند (مانند OpenCL ،ROCm و غیره) یا مجوزهای متفاوتی دارند. برای نمونهای از این درایویشنهای عمومی، بسته magma را ببینید.
نکته
درایویشنها به دلیل یکی از رفتارهای عجیب OfBorg زیر صفت
cudaقرار میگیرند: اگر ارزیابی شکست بخورد (مثلاً به دلیل مجوزهای غیرآزاد)، کل مجموعه صفت دربرگیرنده کنار گذاشته میشود. این امر از کشف، ارزیابی یا ساخت سایر صفات موجود در مجموعه جلوگیری میکند.
passthru.testers
صفات اضافهشده به passthru.testers درایویشنهایی هستند که یک فایل قابل اجرا برای انجام یک تست تولید میکنند. فایل قابل اجرای تولیدشده باید:
- تنظیم محیط، ایجاد پوشههای موقت و مواردی از این دست را انجام دهد.
- بهعنوان
meta.mainProgramدرایویشن ثبت شود تا بتوان آن را مستقیماً اجرا کرد.
نکته
تسترهایی که همیشه به CUDA نیاز دارند باید در
passthru.testers.cudaقرار گیرند، در حالی که موارد عمومی باید درpassthru.testersقرار داده شوند.
مجموعه صفات passthru.testers امکان اجرای تستها در خارج از محیط ایزوله (sandbox) Nix را فراهم میکند. دلایل متعددی برای مفید بودن این قابلیت وجود دارد، زیرا چنین تستی:
- هنگام استفاده در کنار ابزارهایی مانند
nixGLیاnix-gl-hostمیتواند روی سیستمهای غیر NixOS اجرا شود. - دارای الگوهای دسترسی به شبکه است که ایزولهسازی آنها دشوار یا غیرممکن است.
- میتواند خروجیهایی تولید کند که قطعی نیستند، مانند اطلاعات زمانبندی.
passthru.tests
صفات اضافهشده به passthru.tests درایویشنهایی هستند که تستها را داخل محیط ایزوله (sandbox) Nix اجرا میکنند. تستها باید:
- در صورت امکان، از فایلهای قابل اجرای تولیدشده توسط
passthru.testersاستفاده کنند تا از تکرار منطق تست جلوگیری شود. - شامل
requiredSystemFeatures = [ "cuda" ];باشند (اگر عمومی هستند، ترجیحاً مشروط به مقدارcudaSupport) تا اطمینان حاصل شود که فقط روی سیستمهای دارای پردازنده گرافیکی با قابلیت پشتیبانی از CUDA اجرا میشوند.
نکته
تستهایی که همیشه به CUDA نیاز دارند باید در
passthru.tests.cudaقرار گیرند، در حالی که موارد عمومی باید درpassthru.testsقرار داده شوند.
این موضوع برای تستهایی مفید است که قطعی هستند (به عنوان مثال، بررسی کدهای خروج) و میتوان تمام منابع لازم را در محیط ایزوله (sandbox) در اختیار آنها قرار داد.