واحدهای پردازش گرافیکی (GPU) در ابتدا به عنوان ماشین‌های محاسباتی همه‌منظوره طراحی نشده بودند. دلیل وجود آن‌ها حل یک مشکل خاص و به‌شدت پرزحمت بود: رندرینگ سه‌بعدی بی‌درنگ (Real-time 3D Rendering). در اوایل دهه 1990، بازی‌های انقلابی مانند Doom و Quake به پردازش میلیون‌ها رأس (Vertex)، اعمال محاسبات پیچیده نورپردازی، تبدیل مثلث‌ها به پیکسل‌ها و در نهایت ارائه همه این‌ها با سرعت 30 فریم یا بیشتر در ثانیه نیاز داشتند. پردازنده‌های سنتی کامپیوتر (CPU) به‌هیچ‌وجه نمی‌توانستند با این حجم سرسام‌آور از بار کاری همگام شوند.

پاسخ صنعت به این محدودیت، طراحی یک تراشه اختصاصی بود که منحصراً وظایف گرافیکی را بر عهده می‌گرفت. شرکت انویدیا (NVIDIA) در سال 1999 و با عرضه GeForce 256، واژه «GPU» را رسماً به جهان فناوری معرفی کرد. این پردازنده‌های گرافیکی اولیه از یک خط لوله (Pipeline) تابع‌محور (Fixed-function) استفاده می‌کردند. در این ساختار، رأس‌ها از یک سو وارد می‌شدند، پیکسل‌های رنگی از سوی دیگر خارج می‌گشتند و برنامه‌نویس کوچک‌ترین کنترلی روی مراحل میانی نداشت.

خط لوله کلاسیک تابع‌محور چگونه کار می‌کرد؟

پایپ‌لاین گرافیکی در نسل اولیه خود از پنج مرحله اصلی و غیرقابل‌تغییر تشکیل شده بود که به ترتیب و با دقت بالا عمل می‌کردند:

  • پردازش رأس (Vertex Processing): تبدیل مختصات هر رأس از فضای مدل سه‌بعدی به فضای صفحه نمایش دو‌بعدی با استفاده از ضرب ماتریس.
  • مونتاژ اولیه (Primitive Assembly): گروه‌بندی رأس‌ها در قالب مثلث‌ها، خطوط یا نقاط.
  • رسترایزیشن (Rasterization): تعیین پیکسل‌های روی صفحه که توسط هر مثلث پوشانده می‌شوند.
  • پردازش قطعه (Fragment Processing): محاسبه رنگ نهایی هر پیکسل با بهره‌گیری از بافت‌ها (Textures)، نورپردازی و ترکیب‌بندی رنگ‌ها.
  • خروجی فریم‌بافر (Framebuffer Output): نوشتن رنگ نهایی پیکسل‌ها در یک حافظه میانجی برای ارسال به نمایشگر.

نکته بسیار حیاتی در مورد این مراحل، پردازش همزمان داده‌های مستقل است. هزاران رأس به‌طور موازی تبدیل می‌شدند و میلیون‌ها پیکسل همزمان سایه‌زنی (Shading) می‌گشتند. این موازات ذاتی (Parallelism) باعث شد GPU از روز اول به عنوان یک پردازنده به‌شدت موازی مهندسی شود تا بتواند پاسخگوی حجم بالای درخواست‌ها باشد. مراحل پردازش رأس و قطعه، که در هر فریم میلیون‌ها عنصر مستقل را مدیریت می‌کردند، بعدها به بستر ایده‌آلی برای محاسبات همه‌منظوره تبدیل شدند.

تغییر پارادایم به سمت سایه‌زن‌های برنامه‌پذیر

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

این محدودیت در سال 2001 با معرفی GeForce 3 از انویدیا و Radeon 8500 از شرکت ATI شکسته شد. این محصولات اولین سایه‌زن‌های (Shaders) برنامه‌پذیر را به ارمغان آوردند؛ برنامه‌های کوچکی که روی GPU و برای هر رأس یا پیکسل اجرا می‌شدند. برای اولین بار، برنامه‌نویسان قادر بودند به جای انتخاب از یک منوی از پیش تعیین‌شده، کدهای اختصاصی خود را بنویسند.

زبان‌های اولیه سایه‌زنی بسیار ابتدایی بودند و ساختاری شبیه به زبان اسمبلی مخصوص GPU داشتند. طی چند سال بعد، زبان‌های سطح بالاتری نظیر HLSL از مایکروسافت (2002)، GLSL از OpenGL (2004) و Cg از انویدیا (2003) عرضه شدند. این زبان‌ها به‌مرور شبیه‌تر به زبان برنامه‌نویسی C شدند و از انواع داده‌هایی مانند float4، توابع درونی ریاضی و ساختارهای کنترل جریان پشتیبانی می‌کردند.

یک تحول سخت‌افزاری کلیدی در سال 2006 رخ داد. تراشه GeForce 8800 انویدیا که بر پایه معماری G80 ساخته شده بود، واحدهای سخت‌افزاری مجزای سایه‌زن رأس و پیکسل را در یک استخر واحد از هسته‌های برنامه‌پذیر یکپارچه کرد. در این معماری که به معماری سایه‌زنی یکپارچه (Unified Shader Architecture) معروف شد، هر هسته توانایی اجرای هر نوع دستور سایه‌زنی را پیدا کرد. این دستاورد بزرگ، نیای مستقیم پلتفرمی بود که اندکی بعد با نام CUDA متولد شد.

دوران GPGPU؛ هک تاریخی که همه‌چیز را متحول کرد

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

برای انجام یک ضرب ماتریس ساده، مجبور بودید ماتریس اول را به عنوان یک بافت تصویر (Texture) و ماتریس دوم را به عنوان یک بافت دیگر رمزگذاری کنید و GPU را وادارید که خروجی را به عنوان رنگ پیکسل‌ها محاسبه کرده و مجدداً آن را رمزگشایی نمایید. این روش بسیار پیچیده، کند و مستعد خطا بود، اما توانایی خیره‌کننده موازی‌سازی داده‌ها در GPU، انگیزه ایجاد یک محیط محاسباتی بومی و استاندارد را در دل شرکت انویدیا بیدار کرد؛ رویکردی که در نهایت به تولد معماری CUDA منجر شد.

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