پرش به محتوای اصلی

ساخت درایور GPU لینوکس برای M4 Mac Mini در یک ماه

هکرنیوز۱۴۰۵ شهریور ۲۴, سه‌شنبه، ساعت ۲۳:۰۰حدود 15 دقیقه مطالعه

آدرس مقاله: https://codyho.dev/blog/gpu-driver/ آدرس نظرات: https://news.ycombinator.com/item?id=49717638 امتیاز: 262 # نظرات: 158

پست قبلی وبلاگ: https://codyho.dev/blog/hypervisor-macbook-neo/

TL;DR: من و نیکلاس یک درایور گرافیکی کاملا سازگار با OpenGL ES 3.0 برای M4 Mac Mini و MacBook Neo در حدود یک ماه ساختیم، فرآیندی که معمولا سالها طول می کشد. در اینجا کروم و فایرفاکس WebGL را روی M4 Mac Mini با کامپوزیت کار اجرا می کنند:

مهمتر از همه، درایور آنقدر سریع است که می تواند Minecraft را با سرعت 200 فریم بر ثانیه اجرا کند:

ساخت این درایور شامل مهندسی معکوس AGX ​​(نام اپل برای پردازنده گرافیکی) بسیار پیچیده ABI و اجزای فضای کاربر است. همه این کارها به روشی شفاف و کاملا تمیز و با استفاده از تکنیک‌های تثبیت شده انجام شد. این کد هنوز برای کاربران نهایی آماده نشده است، اما ما به دنبال آن هستیم که آن را در اسرع وقت به کاربران نهایی برسانیم.

پیش از این، من یک Hypervisor برای مهندسی معکوس macOS ساخته بودم. اکنون هدف این شد که واقعا کار مفیدی با آن انجام دهیم، و چه هدفی بهتر از نوشتن یک درایور GPU. GPU در واقع یک نیاز برای هر سیستم مدرن است، در غیر این صورت همه چیز باید CPU ارائه شود که مرتبا کندتر و مصرف انرژی کمتری دارد. هدف ما پیاده سازی درایورهای منطبق با OpenGL (و به زودی Vulkan) برای M4 Mac Mini و MacBook Neo بود.

به طور معمول، ساخت درایور GPU تلاشی است که سال ها طول می کشد. هدف ما این بود که این کار را در چند روز انجام دهیم. به نظر می رسد که روزها بیش از حد خوش بینانه بود، اما هفته ها هنوز یک پیشرفت عظیم است. در آن هفته ها داریم:

در طول این فرآیند، ما به هیچ باینری اپل نگاه نکرده‌ایم، فقط ردیابی سخت‌افزاری (از Hypervisor ما) و سایه‌بان‌هایی که خودمان ساخته‌ایم. برای گرافیک فضای کاربر RE، ما مراقب بودیم که هر حباب اپل مورد نیاز را به عنوان اشیاء مات در نظر بگیریم. ما یکی از دوستانمان را داشتیم که مستنداتی را روی این حباب‌ها 1 نوشت تا بتوانیم خودمان یک پیاده‌سازی اتاق تمیز بنویسیم (که عمدتا با تلاش کورکورانه چیزها ساخته شده بود تا زمانی که کار کند). ما همه آزمایش‌های خود را منتشر کرده‌ایم تا هرکسی بتواند منشأ کار ما را تأیید کند (به مخزن‌های دوقلو agx-re در بخش Deliverables مراجعه کنید).

این پست وبلاگ به دو بخش فضای کاربر و هسته تقسیم شده است. این منعکس کننده شکاف در همه درایورهای GPU مدرن است: هسته مسئول ارتباط با سیستم عامل، تخصیص بافرها و مدیریت زمان بندی است، در حالی که محتوای واقعی آن بافرها و آنچه برنامه ریزی می شود غیر شفاف است. فضای کاربر مسئول درک واقعی نحوه عملکرد GPU و پر کردن آن بافرها با موارد است.

در Apple Silicon، درایور هسته مستقیما با سخت افزار ارتباط برقرار نمی کند. در عوض، با سیستم عامل GPU که یک RTOS سفارشی به نام RTKit را اجرا می کند صحبت می کند. این بدان معناست که اولین گام برای یک درایور هسته صحبت کردن با سخت افزار نیست، بلکه کشف سیستم عامل ABI است.

ABI میان‌افزار آزاردهنده‌ترین بخش این پروژه بود، زیرا اپل به جای انجام کار عاقلانه یعنی ایجاد یک ABI معقول با رابط‌های خوب، اساسا یک درایور هسته معمولی را برداشت، آن را به دو نیم کرد و سپس نیمی از آن را در AGX قرار داد و آن را فریم‌ور نامید، و نیمی دیگر از درایور هسته با استفاده از ساختارهای مشترک در حافظه ارتباط برقرار می‌کرد. بسیاری از این ساختارها دارای فیلدهای متعلق به سیستم عامل هستند (که هرگز نباید آنها را اصلاح کنیم و باید از مهندسی معکوس یاد بگیریم) با فیلدهای کنترل شده میزبان پیوند خورده اند.

برای درک اینکه چقدر ABI پیچیده است، درخت حافظه مشترک در M1/M2 به این صورت است:

Asahi Lina معروف است که همه اینها را طی روزهای طاقت فرسای 12 ساعته برای ساخت درایور هسته M1/M2، یک دستاورد فنی شگفت انگیز، کشف کرد. متأسفانه، ABI میان‌افزار A18 Pro (من کار RE خود را در MacBook Neo شروع کردم و بعدا به M4 Mac Mini پرداختم) بسیار پیچیده‌تر از سیستم‌افزار M1 ABI است که در حال حاضر بسیار پیچیده است:

بسیاری از مسائل دیگر وجود دارد که اصطکاک را به فرآیند RE اضافه می کند. من اسنادی در مورد سیستم عامل ABI داشتم، اما بسیار ناقص بود و صادقانه بگویم که خیلی مفید نبود.

رویکرد من ساده و مبتنی بر رویکردی بود که برای مهندسی معکوس موفقیت‌آمیز ماشین‌های M1/M2 استفاده می‌شد: ببینید macOS چه کاری انجام می‌دهد، آن را دوباره پخش کنید، سپس سعی کنید خودمان این کار را انجام دهیم، که توسط Hypervisor ممکن شده است.

هنگامی که من این رویکرد را برای LLM توصیف کردم، به معنای واقعی کلمه تکرار شد: اولین کاری که انجام داد این بود که منتظر اولین رویداد قابل مشاهده سفت‌افزار بود (به این موارد "kicks" گفته می‌شود)، سپس یک کپی از کل وضعیت حافظه GPU را ذخیره کرد. پس از راه اندازی مجدد، حالت حافظه ذخیره شده را مستقیما در حافظه میزبان کپی کرد، ضربه را انجام داد و شاهد تغییر صفحات خروجی بود. سپس سعی می‌کند این اشیاء را در کد بازسازی کند، همه اشاره‌گرها را دنبال کند و محتوا را معنا کند.

طی آزمایش‌های متوالی، Codex تعداد صفحاتی را که کپی می‌کرد کاهش می‌داد تا زمانی که دیگر حالت پخش مجدد وجود نداشته باشد و همه چیز از منبع ساخته شود. 4 به طرز شگفت انگیزی، متوجه شدم Codex در مورد اینکه چه زمانی باید سخت افزار را بیشتر فشار دهد و چه زمانی باید Hypervisor را اجرا کند و خود حالت را بگیرد، سلیقه خوبی دارد.

سه مشکل عمده وجود داشت و همه به دلیل ناتوانی ما در به دست آوردن تصویری تمیز از کار میزبان بود:

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

من مجبور شدم در این مرحله وارد عمل شوم و روند Codex را بررسی کنم. به نظر می رسد که تلاش می کند تا در اواخر چرخه عمر AGX، جایی که بسیاری از رویدادهای قبلی رخ داده بود، یک عکس را دوباره پخش کند. وقتی به آن گفتم که خیلی زودتر در چرخه عمر AGX، اولین ضبط پس از شروع سیستم عامل، یک عکس برداری را انتخاب کند، Codex تقریبا بلافاصله توانست این مشکل را کشف کند (توصیف کننده تک بایتی نداشت). این چند روز طول کشید.

دومین و تنها مانع اصلی، مسئله محاسبات بود. AGX به طور کلی از دو نوع کار پشتیبانی می کند: محاسبه و رندر. در مسیر معمولی رابط کاربری گرافیکی، کار محاسباتی تنها زمانی برنامه ریزی می شود که مقدار قابل توجهی از کار رندر قبلا اجرا شده باشد. بنابراین، زمان زیادی طول کشید تا یک حجم کار محاسباتی را به تصویر بکشیم، و زمانی که Codex سرانجام انجام داد، 336 مگابایت بود و پخش مجدد آن غیرممکن بود (برای مدت طولانی تلاش کرد). همچنین سعی کرد خود اشیاء را با نگاه کردن به تصویر بسازد و بیش از یک هفته را صرف این کار کرد، اما در نهایت ناموفق بود. فقط مزخرفات زیادی وجود داشت که نمی‌توان از آن سرک کرد.

این با مشکلاتی که از طرف من داشتم تشدید شد – پس از شروع به کار رندر، انتظار داشتم ارسال کار محاسباتی ساده‌تر باشد (سیستم‌افزار ABI برای محاسبه در واقع ساده‌تر است، بنابراین در اینجا درست گفتم)، اما فروتنی‌ام را از دست دادم و فکر می‌کردم که این یک راهپیمایی است که فقط چند ساعت طول می‌کشد. بنابراین، من کار را به درستی برای LLM انجام ندادم.

این مشکل در واقع در جلسه دیگری از Codex به من داده شد. در اصل:

ردیابی با موفقیت ثبت شد. ظرف چند ساعت، Codex آن را تخریب کرد، و ظرف چند روز، Codex کار محاسباتی را آغاز کرد. در مورد اینکه چرا پایگاه کد محاسباتی اصلی کار نمی کند… Codex هیچ ایده ای ندارد. کار و شکسته بسیار شبیه به هم هستند.

در نگاه گذشته، این باید از همان ابتدا استراتژی باشد – کوچکترین عکسبرداری ممکن، در حالت تک کاربر اجرا شود تا نتایج را مختل نکند. من از اشتباهاتم در اینجا برای شماره آخر درس گرفتم:

رندرهای جزئی در نهایت یکی از سخت ترین چیزها برای فهمیدن بود. زمانی رخ می‌دهند که بافر Tiled Vertex (TVB) به اندازه کافی بزرگ نباشد که هندسه فعلی را ذخیره کند (یعنی مثلث‌های زیادی برای ترسیم وجود دارد). در این موارد، دو گزینه وجود دارد و درایور باید از هر دو پشتیبانی کند: یا سایز TVB را افزایش دهید، یا یک رندر جزئی انجام دهید، یعنی بخشی از هندسه را رندر کنید، سپس بافر را با بقیه مثلث ها دوباره بارگذاری کنید و رندر جزئی را تمام کنید.

این رندرهای جزئی بسیار بسیار پیچیده بودند، حتی بیشتر از بقیه کارها، زیرا اساسا به معنای افزودن ذخیره و رزومه به درایور GPU است.

گردش کاری که قبلا کشف کردم در اینجا بسیار مفید بود. Codex توانست یک تراکنش رندر جزئی را مجددا پخش کند و سپس متال شیدر ما را برای اجرای چند رندر جزئی تغییر داد (این کار با چکش زدن یک کاشی منفرد با هزاران مثلث تا زمانی که یک رندر جزئی فعال شود بسیار آسان است) و سپس یاد گرفت که چگونه آنها را دوباره پخش کند. زمانی که Codex یک پخش موفقیت آمیز داشت، فقط زمان بود که یاد بگیرد چگونه آن را بسازد.

در تمام سطوح بالا، کل فرآیند اساسا این بود:

اینها همه کارهای مهندسی معمولی است که LLM ها قطعا قادر به انجام آن هستند.

تنها نکته قابل توجهی که من پیدا کردم این بود که Codex به شدت از Hypervisor برای رفع اشکال‌زدایی که چرا کد آن کار نمی‌کند استفاده کرد، از جمله گرفتن فضای آدرس کامل و مقایسه آن با نمونه‌های خوب شناخته شده. این نوع اشکال زدایی سیستماتیک به همین دلیل است که Codex تا حد زیادی عامل برنامه نویسی مورد علاقه من است.

فضای کاربری A18 Pro با M1/M2 بسیار متفاوت است. دارای فرمت های توصیفگر جدید، یک ISA جدید و یک سری چیزهای جدید دیگر است. جدا از اینکه یک رندر معوق مبتنی بر کاشی است که برای اجرای Metal طراحی شده است، فقط یک GPU متفاوت است.

خبر خوب این است که فضای کاربر RE فرآیند بسیار خوبی دارد. به سادگی یک برنامه متال کوچک بنویسید، آن را کامپایل کنید، اجرا کنید، ببینید چه چیزی تغییر کرده است، سپس آن را جدا کنید و شروع به دست و پنجه نرم کردن با بیت ها کنید تا زمانی که بفهمیم همه آنها چه می کنند. اگر فکر می‌کنید که این یک کار خسته‌کننده، تکراری و تکراری به نظر می‌رسد که LLM در آن بسیار خوب است، درست می‌گویید.

کار RE در دو مرحله انجام شد. برای مرحله اول، من از کلود خواستم هر برنامه فلزی ممکنی را که می تواند پیدا کند نگاه کند و سعی کند یک disassembler، اسمبلر بسازد و فرمت همه توصیفگرها/جریان های فرمان/غیره دیگر مورد نیاز برای درایور GPU را بفهمد. من از کلود خواستم همه چیز را برشمرد، از جمله مواردی که لینوکس نمی تواند از آنها استفاده کند (مانند تسلیت) برای کامل بودن. این موفقیت آمیز بود، اما فقط به این دلیل که کلود می‌توانست برنامه‌ها را از هم جدا کند و سپس دوباره سرهم کند، به این معنا نیست که می‌دانست چگونه خودش یک برنامه بسازد.

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

در این مرحله، نیکلاس drm-shim خود را برای M4 Mac Mini به پایان رساند و برای فاز دوم فضای کاربری RE به من پیوست. ما دو رویکرد متفاوت برای تکمیل درایور فضای کاربر داشتیم:

رویکرد من این بود که سخت افزار RE را در اولویت قرار دهم و بر روی چگونگی کارکرد سخت افزار و تمام دستورالعمل ها تمرکز کنم. سپس یک مشخصات می‌نویسم و ​​به LLM اجازه می‌دهم آن را پیاده‌سازی کند، امیدوارم با انطباق کامل OpenGL و Vulkan به پایان برسد. این بدان معنی است که بیشتر وقت LLM من صرف نوشتن آزمایشات روی سخت افزار می شود، نه در واقع اجرای کد Mesa. ایده این بود که وقتی سخت افزار را فهمیدم، همه چیز دنبال شد.

نیکلاس رویکرد متفاوتی در پیش گرفت، که من آن را به عنوان «اول مسا» توصیف می کنم. اساسا، او سعی کرد ابتدا Mesa را بسازد و فقط RE را برای ایجاد برخی عملکردها انجام می داد. زمان او بین ساخت و آزمایش مسا و اجرای RE تقسیم شد.

به نظر می رسد که نیکلاس به طور قابل توجهی سریعتر از من پیشرفت کرده است، زیرا نماینده من زمان زیادی را صرف کارهای جزئی و بی اهمیت به نام کامل بودن می کند. در مقابل، عامل او به دلیل نیاز به ساختن واقعی Mesa بود، بنابراین از زمان و منابع بسیار موثرتر استفاده کرد. او در نهایت خیلی سریعتر از من حرکت کرد که در نهایت سعی کرد با بررسی هر رفتاری که هنوز متوجه نشده بود از کارش حمایت کند.

این یکی از محدودیت های بزرگ Codex بود که من متوجه شدم. بهترین کلمه‌ای که می‌توانم برای توصیف آن به ذهنم بیاورم «پدانتیک» است – همیشه بسیار کامل است، که در برخی سناریوها می‌تواند یک مزیت بزرگ باشد، اما در برخی مواقع در برخی مماس‌های تصادفی به ضرر هدف کلی در علف‌های هرز گیر می‌کند.

در طول RE ما رفتاری را پیدا کردیم که توسط سخت افزار پشتیبانی می شد اما توسط فلز پشتیبانی نمی شد. این امر با درهم‌تنیدگی مستقیم با بیت‌های دستورالعمل‌های مختلف و برون‌یابی آنچه ممکن است بر اساس آنچه می‌دانیم وجود داشته باشد، پیدا شد، درست مانند کاری که آلیسا روزنزوایگ هنگام RE انجام M1/M2 انجام داد. این شامل:

چند چیز وجود دارد که به نفع ما در هنگام ساختن گرافیک فضای کاربر است. مهم‌تر از همه، مجموعه تست سازگاری Khronos (CTS) در حال حاضر مجموعه کاملی از آزمایش‌هایی است که راننده ما باید آن را بگذراند. به عبارت دیگر، سخت‌ترین و حساس‌ترین بخش کار با LLMها، دادن تست‌های خوب برای زمین‌بندی آن‌ها، از قبل برای ما انجام شده است.

علاوه بر این، مسا در حال حاضر دارای انتزاعات عالی است که زندگی ما را به طور قابل توجهی آسان می کند. پشته OpenGL مدرن در لینوکس به این صورت است:

تنها کاری که باید انجام دهیم این است که بین گالیوم، API داخلی Mesa و معنای سخت افزاری AGX ترجمه کنیم. یکی از بزرگترین بخش‌های این فرآیند، ترجمه از NIR، IR داخلی Mesa که کاملا شبیه LLVM IR است، به ISA اختصاصی AGX است. به عنوان یک امتیاز، می توان از این کامپایلر برای درایور آینده Vulkan استفاده مجدد کرد.

نیکلاس توانست به آرامی ویژگی‌های OpenGL را تکرار کند و فضای کاربر را در حین حرکت باز کند، تا اینکه سرانجام به انطباق کامل OpenGL ES 3.0 دست یافت (تست‌های پشتیبانی‌نشده پسوند اختیاری هستند):

در طول این فرآیند، ما از کارهای موجود M1/M2 بهره بردیم: در حالی که معنای دقیق سخت افزار متفاوت است، شکل کلی مشابه باقی می ماند و بنابراین بسیاری از مبادلات/تصمیمات درست از قبل برای ما گرفته شده بود. در طول زمان ساختن این درایور، مشخص شد که آلیسا روزنزوایگ و دیگرانی که درایور M1/M2 را ساخته‌اند، جادوگران مطلق هستند.

درایور هسته لینوکس: https://github.com/GravityLinux/linux/gravity-m4

مستندات فضای کاربری RE (توده وحشتناکی از شیب LLM، اما کاربردی): کودی نیکلاس

Vulkan 1.4، OpenGL 4.6، OpenGL ES 3.2، OpenCL 3.1، Direct3D 12 (از طریق پروتون)، و ray tracing همگی در محدوده هستند. ما می خواهیم درایور ما به خوبی بهترین درایورهای گرافیکی در جهان باشد.

علاوه بر این، من و نیکلاس می خواهیم همه اینها را بالادست کنیم، اما موانع مهمی وجود دارد. ما از Asahi UAPI اصلاح نشده استفاده کردیم، بنابراین هیچ مشکلی در مورد سیاست گذاری در بالادستی Mesa وجود ندارد، اما به آزمایش بسیار بیشتر، بازبینی انسانی و تبدیل شدن به یک PR قابل بررسی نیاز دارد. همچنین با توجه به اینکه این احتمالا اولین درایور GPU کاملا نوشته شده توسط LLM است و اینکه کد ما استانداردهای بالاتری نسبت به کدهای نوشته شده توسط انسان دارد، انتظار تردید قابل توجهی داریم. ما برای این چالش‌ها آماده‌ایم، اما این چالش‌ها عمدتا انسانی و غیرفنی هستند، که LLM نمی‌تواند به آن کمک کند.

درایور هسته لینوکس یک مشکل بزرگتر خواهد بود، زیرا درایور M1/M2 هنوز بالادست نیست و عملا ما در موقعیتی نیستیم که این مورد را تغییر دهیم. ما فکر می کنیم بهترین رویکرد در اینجا این است که فقط منتظر بمانیم تا آن درایور آپ استریم شود و سپس درایور بالادستی ما بعد از M1/M2 بالادست شود (بعد از همه بازسازی های مورد نیاز + بررسی + تجزیه + هر چیزی). این ممکن است مدتی باشد متاسفانه.

ملخ جوان صبور، ما مشتاقانه منتظر دریافت این کد به زودی در دستان شما هستیم و انتظار ممکن است بسیار کمتر از انتظار شما باشد. از این گذشته ، سیب از درخت دور نمی افتد.

اگر می‌خواهید بخشی از این باشید، از شما دعوت می‌کنیم به سرور Discord ما بپیوندید. برای بحث در مورد ایده‌ها، گپ زدن، یا فقط پاتوق کردن به آنجا بیایید!

من از Codex با GPT-5.6 Sol (که بعدا GPT-6 Astra منتشر شد) برای وظیفه هسته RE استفاده کردم. یکی از بزرگترین مشکلاتی که من به آن برخورد کردم محدودیت های بیش از حد تهاجمی امنیت سایبری بود (من در دسترسی قابل اعتماد ثبت نام نکرده ام).

همانطور که گفته شد، GPT-6 Astra و GPT-5.6 Sol کاملا دیوانه هستند و تا حد زیادی بهترین عملکرد را در سیستم عامل ABI RE دارند، بنابراین این هک ارزشش را داشت.

تا آنجا که من می توانم بگویم، پیاده سازی فضای کاربری M4 و A18 Pro عملا یکسان هستند، تنها تفاوتی که می توانم پیدا کنم این است که یک مقدار در M4 کمی بزرگتر است، مطابق با داشتن هسته های بیشتر. ABI میان‌افزار این دو به‌طور قابل‌توجهی متفاوت است: دومین پردازنده مشترک RTKit در A18 Pro همه چیز را پیچیده‌تر می‌کند. به این ترتیب، A18 Pro از نظر سیستم عامل بیشتر شبیه M5 است تا M4. فضای کاربری M5 شباهت هایی به M4 دارد، به طوری که ISA عمدتا یک ابر مجموعه است، اما برخی از قسمت ها مانند توصیف کننده های بافت آن کاملا متفاوت هستند.

فضای کاربری M5 تا حدی مهندسی معکوس شده است. سیستم عامل ABI آن کاملا مهندسی معکوس است. نمونه اولیه drm-shim ساخته شده و به طور کامل آزمایش شده است. و من فکر نمی‌کنم ارتقای نمونه اولیه به درایور کامل Rust زیاد طول بکشد. اهداف اصلی من M4 Mac Mini و MacBook Neo هستند.

من مطمئن نیستم که هدر کلود در مورد اتاق تمیز نبودن چیست، فکر می‌کنم در مورد کل دستورالعمل «به Apple binaries نگاه نکنید» در agx-re گیج شده است. خود سند به وضوح حاوی اطلاعات آلوده نیست. ↩︎

https://github.com/mischa85/apple-gpu-firmware-abi ↩︎

اگر صفحه‌ای حاوی سایه‌زن پیدا کردیم، این صفحه را دور انداختیم و سایه‌زن خود را به عنوان معیار حق نسخه‌برداری اضافی جایگزین کردیم. ↩︎

خواندن متن کامل در هکرنیوزبه زبان اصلی، در سایت ناشر باز می‌شود
متن اصلی (انگلیسی)

Building a Linux GPU Driver for the M4 Mac Mini in One Month

Article URL: https://codyho.dev/blog/gpu-driver/ Comments URL: https://news.ycombinator.com/item?id=49717638 Points: 262 # Comments: 158

همه‌ی اخبار فناوری