تصور کنید یک سرور استریمینگ بدون نمایشگر دارید که بازیها را در یک ماشین مجازی اجرا کرده و خروجی را با کیفیت بالا پخش میکند؛ حالا این فرآیند با افت عملکردی کمتر از ۲ درصد نسبت به سیستمهای واقعی ممکن شده است. virtio-nvgpu، پروژهای آزمایشی که در ۲۴ سپتامبر ۲۰۲۶ منتشر شد، با حذف کامل لایههای ترجمه API، این دستاورد را محقق کرده است.
سالها بود که اجرای واحد پردازش گرافیکی (GPU) — شبیه به موتور قدرتمندی که تمام محاسبات سنگین تصویری را بر عهده دارد — در ماشینهای مجازی با یک دوراهی سخت همراه بود: یا باید کل کارت گرافیک را از طریق VFIO به یک ماشین اختصاص میدادید (Passthrough) یا هزینهی سنگین ترجمه API را میپذیرفتید. اکثر زیرساختهای ابری و محیطهای مجازیسازی از ابزارهایی مثل Venus استفاده میکردند که هر فراخوانی Vulkan یا OpenGL را سریالسازی میکردند. این فرآیند باعث مصرف شدید چرخههای CPU و ایجاد تأخیری میشد که عملاً گیمینگ و رندرینگ حرفهای را در محیط مجازی غیرممکن میکرد.
همانطور که در تحلیلهای پیشین ما دربارهی بهینهسازی زیرساختهای ابری اشاره کردیم، حذف لایههای میانی کلید افزایش کارایی است. در سیستمهای قدیمی، ماشین مجازی نمیتوانست بافرهای گرافیکی متعلق به میزبان را «ببیند»، بنابراین رمزگذاری سختافزاری NVENC در سمت مهمان بدون بازخوانیهای کند از طریق CPU (CPU readbacks) تقریباً غیرممکن بود. این چالشها در محیطهای ابری منجر به هزینههای عملیاتی بالایی میشود، مشابه آنچه در استقرار Bare Metal برای کاهش هزینههای خروجی داده در مدلهای بزرگ مشاهده کردیم. virtio-nvgpu با انتقال لایه ترجمه از سطح API گرافیکی به سطح درایور هسته (Kernel Driver)، این گره را باز کرده است.
هدف: خط لوله استریمینگ
این پروژه روی یک خط لوله با کارایی بالا تمرکز دارد: یک ماشین مجازی بدون نمایشگر (Headless) که هیچ نمایشگر فیزیکی ندارد. در داخل این VM، یک بازی یا اپلیکیشن با استفاده از Vulkan یا OpenGL رندر میشود. سپس یک کامپوزیتور Wayland در سمت ماشین مجازی، تمام پنجرهها را ترکیب (Composite) میکند. با استفاده از قابلیت CUDA zero-copy import، فریم ترکیبشده به رمزگذار سختافزاری NVENC در سمت مهمان ارسال میشود. نتیجه، یک جریان داده (Bitstream) H.264 یا H.265 است که برای هر فریم تقریباً ۱۰۰ کیلوبایت حجم دارد و سپس به یک کلاینت راه دور استریم میشود.
تمام این خط لوله (رندر $\rightarrow$ ترکیب $\rightarrow$ رمزگذاری) روی GPU در داخل ماشین مجازی اجرا میشود و تنها جریان دادهی فشرده است که از VM خارج میشود. برای دستیابی به این هدف، ماشین مجازی به دسترسی واقعی در سطح درایور به منابع GPU، از جمله هندلهای بافر (Buffer handles)، فنسها (Fences)، اشارهگرهای دستگاه CUDA و نشستهای NVENC نیاز دارد.
مکانیسم عملکرد
به نقل از مستندات این پروژه در گیتهاب، سیستم با فوروارد کردن دستورات ioctl درایور هسته انویدیا بین ماشین مجازی لینوکس و میزبان کار میکند. در این حالت، ماشین مجازی از درایورهای کاربر (User-mode drivers) تغییرنیافته انویدیا استفاده میکند؛ به این معنی که همان کتابخانهها و نسخههای Vulkan که روی سختافزار فیزیکی استفاده میشوند، اینجا نیز به کار میروند.
- درایور هسته مهمان: یک ماژول با مجوز GPL که دستگاههای
/dev/nvidiactlو/dev/nvidia0...Nو/dev/nvidia-uvmرا ثبت میکند. این ماژول درخواستهای ioctl را روی یک صف کنترل (virtqueue) سریالسازی کرده و مناطق حافظه مشترک را با ویژگیهای کشینگ (Caching) صحیح در فرآیند فراخواننده نگاشت میکند. این بخش صرفاً بایتهای خام را کپی میکند و هیچ تصمیمی درباره ABI نمیگیرد. - Device Crate: یک بکاند مبتنی بر زبان Rust (با مجوز Apache-2.0) که هندلهای مهمان را به توصیفگرهای فایل (File descriptors) میزبان ترجمه میکند. این بخش ترجمه آگاه از ABI را برای پارامترهای ioctl انجام داده، اشارهگرهای جاسازی شده و توصیفگرهای فایل را بازنویسی کرده و آنها را علیه دستگاههای میزبان صادر میکند. مدیریت بافرها و پنجرهها در این لایه قرار دارد.
- صف رویداد: یک صف دوم (virtqueue) که از میزبان به مهمان اجرا میشود. میزبان توصیفگرهای باز شده را زیر نظر میگیرد و زمانی که یکی از آنها قابل خواندن شود، سیگنال میفرستد. این کار باعث بیدار شدن مهمان میشود؛ در غیر این صورت، مهمان یک توصیفگر را که به طور دائمی «آماده» گزارش شده است، Polling کرده و باعث اشغال بیهوده CPU میشد.
بنچمارکهای عملکرد
تستها روی یک RTX 3060 (درایور 595.99.02) نشان میدهد که برای هر فریمی که بیش از ۲ میلیثانیه زمان میبرد — که تقریباً تمام بازیهای مدرن را شامل میشود — عملکرد ماشین مجازی در محدوده ۲ درصدِ سختافزار واقعی (Bare metal) است. در یک بارگذاری Vulkan بدون نمایشگر، زمان فریم در میزبان ۳۹ میلیثانیه و در ماشین مجازی نیز دقیقاً ۳۹ میلیثانیه ثبت شد (که در واقع ۰.۴٪ سریعتر از سختافزار بود و در محدوده نویز اندازهگیری قرار دارد).
جزئیات اندازهگیریها بر اساس اندازه فریم به شرح زیر است:
- فریم ۹.۹ میلیثانیهای: ۰.۷٪ سریعتر
- فریم ۲.۰ میلیثانیهای: ۱.۷٪ کندتر
- فریم ۰.۵ میلیثانیهای: ۷.۱٪ کندتر
در فریمهای زیر ۲ میلیثانیه، هزینه بیدار کردن GPU (حدود ۰.۰۲ میلیثانیه) مشهود میشود. برای فریمی که تنها ۰.۰۵ میلیثانیه زمان میبرد، این موضوع منجر به سربار ۴۰.۸٪ میشود. با این حال، برای هر فریم استاندارد در بازیها، این سربار ناچیز است.
سربار CPU در طول حلقه رندر تقریباً صفر است. زیرا درایور کاربر انویدیا دستورات را از طریق حافظه نگاشتشدهای میفرستد که میزبان از قبل مالک آن است، بنابراین در طول فراخوانیهای Draw، عملاً هیچ چیزی «فوروارد» نمیشود. در تستی با نرخ ۱۰۰ فریم بر ثانیه به مدت ۱۲ ثانیه، میزبان در حالت سختافزار واقعی ۰.۴۰ ثانیه و در حالت ماشین مجازی ۰.۳۷ ثانیه از CPU استفاده کرد. در طول ۸۱۳,۶۹۱ فریم، بکاند تنها مجبور به پردازش ۱۳,۷۹۲ پیام شد (یک عبور در هر ۵۹ فریم) که تقریباً تمام آنها مربوط به تنظیمات اولیه دستگاه بود.
قابلیتهای چند-مستأجری
این پروژه اشتراک بهینه GPU را نیز به نمایش گذاشته است. چهار ماشین مجازی روی یک RTX 3060 با بار کاری یکسان توانستند نرخ فریمی به ترتیب ۲۵.۸۴، ۲۶.۴۹، ۲۵.۵۷ و ۲۵.۷۹ را ثبت کنند. مجموع نرخ فریم آنها ۱۰۳.۷ بود، در حالی که یک ماشین مجازی تنها ۱۰۲.۹ فریم بر ثانیه ثبت کرده بود. هر ماشین مجازی زمان فریم p50 تقریباً ۳۹.۱۶ میلیثانیه را حفظ کرد که نشاندهنده تقسیم تقریباً کامل منابع تا چهار رقم اعشار است.
نکته کلیدی این است که هر چهار ماشین مجازی توانستند همزمان ویدیوهای H.264 را با نرخ ۶۰ هرتز از طریق NVENC رمزگذاری کنند، بدون اینکه با محدودیتهای نشست (Session limits) مواجه شوند. این ثابت میکند که مهمان کنترل واقعی در سطح درایور بر منابع GPU، از جمله هندلهای بافر و اشارهگرهای دستگاه CUDA دارد. اگرچه چهار مهمان تست شدند، اما این یک محدودیت کشف شده نبود.
محدوده و محدودیتها
با وجود نتایج امیدوارکننده، این پروژه صراحتاً آزمایشی است. در حال حاضر پروفایلهای ABI خاصی را پشتیبانی میکند و هدف آن استریمینگ بدون نمایشگر است.
موارد تأیید شده:
- شناسایی دستگاه توسط
nvidia-smi(گزارش واقعی توان، حافظه و deviceUUID میزبان). - رندرینگ Vulkan: خروجی
vulkaninfoبرابر ۰ است و ترسیمهای Offscreen از نظر پیکسلی دقیق هستند. - ارائه Wayland از طریق یک کامپوزیتور در سمت مهمان.
- رمزگذاری NVENC از طریق Vulkan Video و رمزگذاری روی دستگاه کلاینت.
- بافرهای وارد شده (Imported buffers) که از طریق یک پنجره مشترک به عنوان حافظه میزبان نگاشت شدهاند.
موارد پیادهسازی نشده یا تست نشده:
- بیش از چهار ماشین مجازی (هشت ماشین تست نشده است).
- بارهای کاری سنگینتر از
vkcubeدر رزولوشن 720p. - استفاده از چندین کارت گرافیک یا نسخههای مختلف درایور به صورت همزمان.
- قابلیتهای CUDA فراتر از شناسایی (بخش jailer و پوشش چند-مستأجری هنوز ساخته نشدهاند).
- تابع
cudaMallocManaged()یا حافظه مجازی یکپارچه (Unified Virtual Memory) کامل. - خروجی نمایشگر فیزیکی (Scanout).
- تکنولوژیهای MIG یا SR-IOV.
نسخههای درایور و پروفایلهای ABI
از آنجا که ABI درایور هسته انویدیا ناپایدار است و ساختار structها بین نسخهها تغییر میکند، پشتیبانی از طریق پروفایلهای ABI صریح انجام میشود. پروفایلهای ارسالی شامل موارد زیر است:
- 535.129.03: پوشش این نسخه تا پروفایل بعدی.
- 580.178.04: پوشش این نسخه تا پروفایل بعدی.
- 595.71.05: پوشش این نسخه و نسخههای جدیدتر.
هر نسخهای قدیمیتر از ۵۳۵.۱۲۹.۰۳ رد میشود تا از «پاسخهای احتمالاً غلط» ناشی از ساختارهای دادهای نادرست جلوگیری شود. درایوری که بسیار جدیدتر از آخرین پروفایل باشد، با این فرض پذیرفته میشود که ABI تغییر نکرده است.
پروفایلها به صورت مکانیکی ساخته میشوند. بخش struct از open-gpu-kernel-modules انویدیا با کامپایل پروبها برای هر فیلد جهت خواندن sizeof و offsetof استخراج میشود. بخش تصمیمگیرنده که دستورات ایمن را تعیین میکند، از nvproxy دنبال میشود. در اجراهای واقعی، نسخه 595.99.02 روی RTX 3060 کاملاً بنچمارک شد و نسخه 615.71.09 روی RTX A2000 برای شناسایی و رندر تایید شد.
ساختار مخزن و مجوزها
پروژه برای ایجاد تعادل بین الزامات هسته و انعطافپذیری VMM، از سه منطقه مجوز مختلف استفاده میکند:
driver/(GPL-2.0): ماژول هسته مهمان. دستگاهها را ثبت کرده و ioctlها/mmaps را بدون آگاهی از ABI روی virtqueue فوروارد میکند.device/(Apache-2.0): دستگاه virtio به عنوان یک Rust crate. این بخش مستقل از VMM است و تمام مسائل VMM از طریق traitها (مانند زنجیرههای توصیفگر به عنوان Read/Write) مدیریت میشوند.protocol/(BSD-3-Clause یا GPL-2.0+): فرمت سیم (Wire format) مشترک و تعاریف ABI که دارای مجوز دوگانه است تا هم درایور GPL و هم crate آپاچی بتوانند از هدرهای یکسانی استفاده کنند.gen/: جداول ABI تولید شده و بازتولیدپذیر.isolate/(Apache-2.0): یادداشتی برای طراحی یک کمکی (Helper) ایزوله برای هر مهمان در آینده که FDهای واقعی دستگاه را نگه دارد. در حال حاضر، بکاند اینها را در فرآیند VMM نگه میدارد.
مقایسه معماری
در مقایسه با Venus، تفاوت ساختاری عظیم است. Venus در هر فریم هزاران بار مرز VM را (برای هر فراخوانی API) قطع میکند که منجر به سربار شدید CPU و تأخیر میشود. virtio-nvgpu این مرز را تنها چند بار در هر فریم (برای هر ioctl) قطع میکند.
| ویژگی | Venus | virtio-nvgpu |
|---|---|---|
| عبور از مرز VM | هر فراخوانی (هزاران بار در فریم) | هر ioctl (۵ تا ۲۰ بار در فریم) |
| تولید دستورات | در میزبان (Host) | در مهمان (Guest) |
| سربار CPU | بالا (سریالسازی/بازپخش) | نزدیک به صفر برای رندرینگ |
| مالکیت بافر | میزبان مالک است | مهمان مالک است |
| NVENC مهمان | غیرعملی | فعال (تعامل واقعی CUDA) |
این رویکرد مشابه موفقیت /dev/dxg در WSL2 و DRM native context مورد استفاده اینتل و AMD است و بالاخره قابلیت مشابهی را به اکوسیستم انویدیا میآورد، جایی که پیش از این هیچ native context وجود نداشت. همچنین از nvproxy (در gVisor) برای ترجمه ABI در کانتینرهای ایزوله و از chromeos/virtio-media برای ساختار مخزن الهام گرفته است.
این تغییر در مجازیسازی GPU به این معناست که ابرهای گرافیکی با تراکم بالا اکنون میتوانند عملکردی نزدیک به سختافزار را بدون صلبیتِ Passthrough کامل ارائه دهند. این امر مانع ورود برای استقرار کانتینرها و ماشینهای مجازی شتابیافته با GPU را که نیاز به ادغام عمیق درایور برای رمزگذاری و محاسبات دارند، کاهش میدهد. این بهینهسازی در مدیریت منابع سختافزاری، گامی در جهت دسترسی به مدلهای بهینهتر است، مشابه تلاشهای صورت گرفته برای اجرای مدلهای mini-AGI روی سختافزارهای محدود با VRAM پایین جهت افزایش دسترسی کاربران به هوش مصنوعی.
گام بعدی شما
- اگر توسعهدهنده زیرساختهای ابری هستید، مخزن گیتهاب این پروژه را برای تست در محیطهای Headless بررسی کنید.
- برای کاهش هزینههای استنتاج در محیطهای مجازی، مدلهای انتقال در سطح درایور را جایگزین ترجمههای API کنید.
- وضعیت پشتیبانی از نسخههای جدیدتر درایور انویدیا را در پروفایلهای ABI دنبال کنید.
اما داستان سختافزاری این تحول حتی شگفتانگیزتر است — به تحلیل ما دربارهی تراشههای Blackwell مراجعه کنید.
![[آزمایشی] دستگاه virtio برای دسترسی نزدیک به بومی GPU انویدیا در ماشینهای مجازی KVM.](/_next/image?url=https%3A%2F%2Fwww.dothoosh.com%2Fmedia%2F989dbaad-32ec-4ada-b338-d18f43170c89-github---nestrilabs-virtio-nvgpu-experimental-a-virtio-device-for-near-native-nvidia-gpu-access-in-kvm-virtual-machines-74edeb25.webp&w=1920&q=75)



گفتگو