با معماری موازی‌ سازی کمپانی پیشتاز صنعت GPU آشنا شوید؛ NVIDIA CUDA

با معماری موازی‌ سازی کمپانی پیشتاز صنعت GPU آشنا شوید؛ NVIDIA CUDA


مقدمه

آینده محاسبات در اختیار واحد پردازش گرافیکی (Graphics Processing Unit) یا GPU است. GPU ها نشان می‌دهند که کارت‌های گرافیکی در زمینه پردازش تصویر (Image Processing)، شتاب بخشیدن به رندر صحنه‌های 3 بعدی، و توانایی محاسباتی که GPU ها دارند، آنها را به واحد پردازش موازی بزرگی توسعه داده است. برنامه ریزی یک پردازشگر گرافیکی برای انجام وظایف موازی سازی کاملا ساده است. اما پس از درک جنبه های مختلف پردازشگر گرافیکی، می توان از آن برای انجام وظایف دیگر به خوبی استفاده نمود. در این مقاله نشان خواهیم داد که CUDA چگونه می تواند از قدرت عظیم GPU ها استفاده کند. CUDA معماری موازی کمپانی انویدیا است. این معماری با بهره گیری از قدرت GPU، باعث افزایش چشمگیر در کارایی پردازش های محاسباتی می شود.

 

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

برگرفته شده از Advanced Computing: An International Journal ( ACIJ ), Vol.3, No.1, January 2012 با اندکی دخل و تصرف.

معرفی

محاسبات GPU لبه ی بزرگی روی CPU با توجه به سرعت پردازش فراهم کرده است. از این رو، یکی از جالبترین زمینه های تحقیق در زمینه تحقیقات و توسعه صنعتی مدرن است. GPU یک پردازشگر گرافیکی است که شما را قادر می سازد تا کیفیت گرافیکی بالایی‌ را روی رایانه‌ی خود اجرا کنید که از محاسبات مدرن انتظار می‌رود. مانند CPU، این واحد نیز یک پردازشگر با یک چیپ واحد است. با این حال، مانند تصویر زیر، GPU دارای صدها واحد Core در مقایسه با CPU های 4 یا 8 هسته‌ای است. کار اصلی GPU، پردازش توابع 3 بعدی است. زیرا این نوع از محاسبات برای CPU بسیار سنگین می‌باشند. GPU می‌تواند به کامپیوتر برای اجرای موثرتر کمک کند. گرچه GPU برای اهداف گرافیکی ساخته شده است، اما در حال حاضر به انجام محاسبات با دقت و کارایی بالا تکامل یافته است. تکامل GPU در طول سالها به سمت کارایی بهتر ممیز شناور حرکت کرده است. کمپانی NVIDIA معماری به شدت موازی سازی خود را تحت عنوان “CUDA” در سالهای 2006 الی 2007 معرفی کرد و کل چشم انداز برنامه نویسی GPGPU را تغییر داد. معماری CUDA دارای تعدادی واحد Core است که با یکدیگر کار کرده و مجموعه داده های (Data set) داده در برنامه را خرد می کند. محاسبات GPU یا GPGPU، از GPU استفاده کرده تا محاسبات عمومی و محاسبات مهندسی را انجام دهد. مدل محاسباتی GPU، استفاده از CPU و GPU با یکدیگر در یک مدل محاسباتی کمک پردازشی ناهمگن (heterogeneous co-processing computing model) است. قسمت sequential یا ترتیبی برنامه روی CPU اجرا شده و بخش محاسباتی فشرده ی برنامه توسط GPU تسریع بیشتری خواهد گرفت. از دید کاربران، برنامه سریعتر است زیرا، برنامه از کارایی بهتر GPU استفاده کرده تا کارایی خود را بهبود بخشد.

 

مقایسه CPU و GPU در جدول زیر آمده است. همانطور که میبینم، CPU برای مدیریت وظایفت مختلف سیستم عامل مانند صف بندی job ها و مدیریت حافظه کارآمدتر است. درحالیکه نقطه قوت GPU در عملیات های ممیز شناور نهفته است.

  نتایج تست AIDA64 GPGPU در مقایسه پردازنده های 4، 8 و 10 هسته ای با کارت گرافیک 2816 هسته ای GTX980Ti (تستی که مدت ها پیش برای مقاله‌ی آشنایی با ساختار کارت گرافیک آماده کرده بودیم) بیانگر همین موضوع است. نتیجه گیری به دست آمده، کاملا بیانگر این است که CPU و CPU هر کدام مختص به انجام وظایفی هستند:

 

GPGPU

قابلیت های GPU به صورت سنتی بسیار محدود است. در واقع برای سالها از GPU در جهت تسریع بخشیدن به پایپ لاین های گرافیکی استفاده میشد. ظرفیت پردازش GPU به vertice  ها (رئوس) و fragment های مستقل محدود است (در گرافیک کامپیوتری، یک fragment داده های لازم مانند عمق برای تولید یک پیکسل مجزا برای رسم اولیه در فریم بافر است). اما این پردازش می تواند به صورت موازی با استفاده از Core های موجود در GPU انجام شود. این امر به ویژه هنگامی مفید است که برنامه نویسان می خواهند vertice ها و fragment های زیادی را به همه نوع شیوه ای پردازش کنند. از این رو، GPU ها پردازشگرهایی هستند که می توانند با اجرای یک کرنل مجزا روی تعداد زیادی از رکوردها در یک stream فورا به صورت موازی، به انجام عملیات بپردازند. به صورت ساده، یک stream یا جریان، مجموعه ای از رکوردها است که به محاسبات مشابه نیاز دارد. Stream ها موازی سازی داده ها را فراهم می کنند. می توانیم چندین ورودی و خروجی به صورت همزمان داشته باشیم و این امر GPU را قادر می سازد تا موازی سازی داده را داشته باشد، بطوریکه معماری GPU دارای ALU عظیم است و شامل پایپ لاین های vertex  و  fragment می باشد. این موضوع باعث قدرت محاسباتی فوق العاده در GPU خواهد شد. اما این ظرفیت محاسباتی در مراحل تکاملی گذشته ی GPU استفاده نشده بود. استفاده از GPU برای پردازش موجودیت های غیر گرافیکی به عنوان General Purpose GPU یا GPGPU شناخته می شود. به طور سنتی، GPU برای ارائه راه حل های گرافیکی بهتر برای محیط های موجود استفاده می شد. اگر ما از GPU برای محاسبات وظایف فشرده استفاده کنیم، این عمل به GPGPU معروف است. این موضوع برای انجام عملیات های پیچیده ی ریاضی به صورت موازی سازی برای دستیابی به پیچیدگی زمانی کمتر استفاده می شود. قدرت محاسباتی GPGPU نتیجه ی معماری بسیار تخصصی آن است.

 

CUDA

CUDA مخفف Compute Unified Device Architecture به معنای معماری محاسباتی دستگاه یکپارچه، معماری موازی سازی کارتهای گرافیکی کمپانی NVIDIA است و خود را به عنوان یک معنی جدید برای محاسبات چند منظوره با GPUها معرفی می کند. البته CUDA تا به امروز نسخه های مختلفی را به خود دیده است که بحث ما در مورد مدل کلی CUDA است. CUDA C/C++ یک زبان برنامه نویسی توسعه یافته از C/C++ برای محاسبات چند منظوره یا General Purpose Computation است. CUDA توانایی محاسباتی عظیمی به برنامه نویسی می دهد. این توانایی محاسباتی موازی سازی عظیم توسط کارت های گرافیک NVIDIA فراهم شده است.

(شکل2) جریان execution در GPU

 

برای مثال، کودا حداقل 128 پردازنده کمک عملیاتی فراهم می کند. برای اجرای برنامه های چندنخی، نیازی به محاسبات جریانی در GPU نیست، زیرا هسته ها می توانند با یکدیگر ارتباط برقرار کرده و به تبادل اطلاعات با یکدیگر بپردازند. CUDA تنها برای الگوریتم های بسیار موازی مناسب و مفید است. اگر شما قصد دارید زمانیکه الگوریتم خود را روی GPU اجرا می کنید کارایی آن را افزایش دهید، باید نخ های بسیار زیادی داشته باشید. به طور نرمال، تعداد زیاد نخ ها به کارایی بهتر منجر خواهند شد. برای اکثر الگوریتم های سریالی، CUDA مناسب نیست. اگر مسئله حداقل قابل تقسیم به هزار نخ نباشد، در این صورت استفاده از CUDA مزیت کلی در پی نخواهد داشت. در این صورت می توانیم الگوریتم های سریالی را به موازی تبدیل کنیم اما این موضوع همیشه امکان پذیر نیست. همانطور که در مورد به دست آوردن بهترین بهینه سازی گفتیم، باید مسئله را حداقل به هزار نخ تقسیم کنید. سپس کارایی الگوریتم شما سریعا افزایش خواهد یافت. CUDA می تواند در هنگام نوشتن زبان C به طور کامل مورد استفاده قرار گیرد. همانطور که قبلا عنوان شد، ایده ی اصلی CUDA این است که هزاران نخ در حال اجرا به طور موازی داشته باشیم. همه ی این نخ ها قصد اجرای تابع بسیار مشابهی (کد) را دارند که به عنوان یک Kernel شناخته می شود. تمام این نخ ها با استفاده از دستور العمل مشابه و داده های مختلف، اجرا یا execute می شوند. هر نخ شناسه یا ID خود را می داند و بر اساس شناسه خود، تعیین می کند که کدام قسمت از داده اجرا گردد. یک برنامه مبتنی بر CUDA شامل یک یا چند فاز است که بر روی میزبان (CPU) یا یک دستگاه مانند GPU اجرا می شود. همان طور که در شکل 2 نشان داده شده است، هیچ موازی سازی داده در کد میزبان به چشم نمی خورد اما، در کد دستگاه یا GPU که شامل مقدار زیادی از موازی سازی داده است، موازی سازی انجام می گیرد. یک برنامه CUDA در واقع یک منبع کد یکپارچه است که شامل کدهای میزبان و دیوایس می‌باشد. کد میزان کد ارسال مستقیم در C است و در مرحله بعد تنها با کمک کامپایلر استاندارد C کامپایل شده است. این همان چیزی است که ما می توانیم درباره فرایند عادی CPU بگوییم. کد دستگاه با استفاده از کلمات کلیدی CUDA برای برچسب زدن توابع داده های موازی (که کرنل نامیده می شود) و ساختارهای داده های انجمنی آنها نوشته شده است. در برخی موارد اگر GPU در دسترس نباشد، می توان کرنل ها را روی پردازنده اجرا نمود. این امکان با کمک ویژگی های شبیه سازی فراهم شده است و کیت توسه نرم افزاری CUDA این ویژگی ها را فراهم کرده است. یکی از مزیت های این مورد آن است که نیازی به نوشتن کل برنامه با استفاده از تکنولوژی CUDA نیست. اگر در حال نوشتن یک برنامه ی طولانی هستید، با یک رابط کاربری و بسیاری از توابع دیگر، بیشتر کد شما در قالب C++ یا زبان دیگری که انتخاب کردید، نوشته خواهد شد.

 

معماری 

 GPU یک معماری به شدت موازی است. بسیاری از مسائل با استفاده از محاسبات GPU می توانند به طور موثر حل شوند. GPU ها دارای توان محاسباتی بالایی هستند. آنها میزان برنامه ریزی را در پایپ لاین افزایش می دهند.

(شکل 3) معماری GPU

 

شکل 3 یک GPU با قابلیت CUDA را نشان می دهد. CUDA را می توان به عنوان یک مجموعه یا آرایه هایی از پردازنده های جریانی نگریست که قادر به اجرای درجه ی بالایی از چند نخی هستند. در شکل 3، هر دو واحد SM (Streaming Multiprocessor) تشکیل یک بلاک (block) را می دهند. البته تعداد واحد های SM در یک ساختمان یک بلاک می تواند در نسل های مختلف GPU های CUDA متفاوت باشد. همچنین هر واحد SM دارای تعدادی پردازندن های جریانی یا SP است که Control Logic و Ins Cache را به اشتراک می گذارند. هر GPU در حال حاضر می تواند بیش از 4 گیگابایت حافظه ی Graphics Double Data Rate (GDDR) را در اختیار داشته باشد. RAMهای GPU با CPU متفاوت است زیرا آنها به عنوان بافر حافظه برای رندر گرافیکی استفاده می شوند. برای برنامه های گرافیکی، آنها تصاویر ویدئویی و اطلاعات بافت رندرینگ 3 بعدی را نگه می دارند. اما برای محاسبات، آنها به عنوان حافظه بیرون از GPU با پهنای باند بسیار بالا عمل می کنند؛ هر چند با تاخیر نسبتا بیشتر نسبت به حافظه اصلی سیستم. برای برنامه های به شدت موازی سازی، پهنای باند تاخیر بیشتری را در پی دارد.

 

واحد های پایه ای در CUDA

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

(شکل 4) معماری CUDA

 

GRID

یک GRID به گروهی از Threadها یا نخ ها گفته می شود که در حال اجرای Kernel مشابه هستند. این تردها با هم همگام نیستند. هر تماس با CUDA از CPU از طریق یک Grid انجام می شود. استارت یک Grid در CPU یک عملیات همگام است. اما Grid های چندگانه می توانند یک بار اجرا شوند. در سیستم های multi-GPU، این Grid ها نمی توانند بین GPU ها به اشتراک گذاشته شوند زیرا آنها از Grid های متعدد برای حداکثر کارایی استفاده می کنند.

 

Block

Grid ها از بلاک ها تشکیل شده اند. هر بلاک یک واحد منطقی است که شامل تعدادی از Thread های هماهنگ و مقدار مشخصی از حافظه ی اشتراکی است. درست همانطور که Gridها، بین GPU ها به اشتراک گذاشته نمی شوند، بلاک ها بین multiprocessors ها به اشتراک گذاشته نمی شوند. تمام بلاک های موجود در یک Grid از برنامه ی مشابهی استفاده می کنند. متغیری به نام blockIdx می تواند برای شناسایی بلاک فعلی استفاده شود. ID یا شناسه ی بلاک ها با توجه به نوع بعد Gridها، می تواند یک بعدی یا دو بعدی باشد. معمولا 65,535 بلاک در GPUوجود دارد.

 

Thread

بلاک ها از تردها ساخته شده اند. تردها بر روی هسته های multiprocessor ها اجرا می شوند، اما بر خلاف Grid ها و بلاک ها، آنها به یک هسته محدود نمی شوند.  مانند بلاک ها، هر ترد دارای یک شناسه (ID) به نام threadIdx است. با توجه به نوع بعد بلاک ها، شناسه تردها می تواند 1 بعدی ،2 بعدی و یا 3 بعدی باشد. شناسه ی تردها مربوط به بلاکی است که در آن قرار دارد. تردها دارای مقدار مشخصی از حافظه های ثبات هستند. معمولا در هر بلاک 512 ترد وجود دارد.

 

نوع حافظه CUDA

(شکل 5) ساختار CUDA

 

Global Memory

این یک حافظه ی خواندن و نوشتن است. سرعت آن پایین، فایده کش و نیازمند 16 بایت متوالی و هم تراز خواندن و نوشتن است تا سریع شود (خواندن/نوشتن تلفیقی).

 

Texture memory

این یک حافظه فقط خواندن است. کش آن برای الگوی دسترسی به حافظه 2 بعدی بهینه سازی شده است.

 

Constant memory

جایی است که ثابت ها (constants) و آرگومان های کرنل ذخیره می شوند.  اما حافظه کند، اما دارای کش است.

 

Shared memory

تمام تردهای موجود در بلاک می توانند از حافظه اشتراکی برای عملیات های خواندن و نوشتن استفاده کنند. این موضوع برای تمام تردهای موجود در بلاک رایج است و و سایز این حافظه کمتر از سایز حافظه Global می باشد. تعداد تردهایی که همزمان می توانند در یک بلاک اجرا شوند حافظه اشتراکی را تعیین می کند که مشخص شده است و میزان اشغال شده ی بلاک را نشان می دهد.

 

Local memory

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

 

Registers

این احتمال دارد سریعترین حافظه ای باشد که در دسترس است. یک مجموعه از ثبات ها به هر ترد داده می شود و از آن برای ذخیره سازی سریع و بازیابی اطلاعات ماننده شمارنده ها استفاده می شود که غالبا توسط یک ترد استفاده می گردد.

 

APPLICATIONS

CUDA برای بسیاری از برنامه ها می تواند مناسب باشد که در اینجا مروری به برخی از آنها خواهیم داشت:

•         Seismic Database – 66x to 100x speedup (پایگاه داده لرزه ای)

•         Molecular Dynamics – 21x to 100x speedup (دینامیک مولکولی)

•         MRI processing – 245x to 415x speedup (پردازش تصاویر MRI)

•         Atmospheric Cloud Simulation – 50x speedup (شبیه سازی ابر جوی)

•         Video Encoding

•        3D Rendering

  در انتها چنانچه سوالی دارید، در قسمت نظرات مطرح کنید.

پست های مرتبط

دیدگاه خود را بنویسید