پردازش موازی ( آشنایی با کودا) بخش سوم

سلام
طبق قولی که تو قسمت قبل دادم قراره که از این قسمت بحث مربوط به CUDA رو شروع کنیم. هدف از این سری مطالب اینه که شما در آخر بتونین ضرب دو ماتریس n در n رو انجام بدید که خب فکر میکنم برای آشنایی با CUDA کافی باشه.
CUDA یا Compute Unified Device Architecture در واقع همونطور که از اسمش مشخصه یک ساختاره. ساختاری که قراره کار برنامه نویسارو برای پردازش موازی راحت کنه. اما بریم سر اصل مطلب: قسمت نرم افزار.
CUDA در قسمت نرم افزار رو میتونیم به چند قسمت تقسیم کنیم. یکی نرم افزاری که برای اجرا ( runtime ) وجود داره که روی تمام درایور ها از سال ۲۰۰۶ موجوده و در واقع وظیفه ی اصلی رو داره و یکی هم کامپایلر مخصوصه اونه که توسط شرکت nvidia عرضه میشه. تنها وظیفه کامپایلر جدا کردن کد مخصوص به GPU از CPU و فرستادن کد مخصوص CPU برای کامپایله. اما وظیفه ی اصلی رو بخش runtime به عهده داره. وظیفه ی این بخش کامپایل کد مخصوص جی پی یو و همچنین اجرا کردن توابع به صورت موازیه.
هرکسی با CPU و پردازش موازی با اون کار کرده باشه میدونه که نوشتن برنامه ای که بتونه دو تا ماتریس یک بعدی رو به صورت موازی با هم جمع کنه کار سختیه. تازه اگر به صورت موازی اجرا بشه که ممکنه این اتفاق هم نیفته. اما بذارید تابع جمع ماتریس رو به صورت عادی بنویسیم و بعد به کودا منتقلش کنیم. خودتون تا آخر این قسمت خواهید دید که تا چه حد برنامه نویسی موازی با کودا ساده تره.

[cpp] void adder(int *a, int *b, int *c)
{
int idx=0;
while(idx<N)
{
c[idx]=a[idx]+b[idx];
idx++;
}
}
[/cpp]

ممکنه که بگید این برنامه رو میشه ساده ترم نوشت. اما برای اینکه بتونید راحت تر با نمونه‌ی کوداییش مقایسه کنید این برنامه بهتره.
حالا نگاهی به همون تایع بالا میندازیم و این بار یه صورت موازی و کودایی(!) درش میاریم:

[cpp] __global__ void adder(int *a,int *b,int *c)
{
int idx=blockIdx.x;
if(idx<N)
c[idx]=a[idx]+b[idx];
}
[/cpp]

همونطور که ملاحظه می کنید چقدر راحت نابع قبلی به صورت موازی نوشته شد.
اما میرسیم به تفاوت این دو تابع : در اینجا دو تا تفاوت عمده می بینید : یکی عامل شناسایی (identifier) به نام __global__ و یکی هم تغییر نوع مقدار دهی به متغیر idx .
اولی مشخص میکنه که این تابع قراره روی GPU اجرا بشه.( از این مدل عوامل شناسایی(!) یک نوع دیگم داریم : __device__ که البته موضوع بحث ما نیست.)
برای توضیح دومی باید برگردیم به سطح سخت افزار و واسط نرم افزاری اون.

اول از سطح سخت افزار شروع میکنیم. همونطور که قبلا هم گفتم GPU از thread ها ساخته شده و دونستن همین موضوع هم کافیه.

حالا میایم سر نرم افزار : هر کدوم از این thread ها یک شماره ی مخصوص به خودشون رو دارند که اصطلاحا [به اونا] index گفته میشه(Idx) این شماره ها به runtime کمک میکنه که برای هر thread تابع مخصوص به خودشو تولید و سپس اجرا کنه. این یعنی چه؟ به شکل زیر که ساختار بک GPU فرضی با چهار هسته رو نشون می ده توجه کنید:

همونطور که میبینید هر هسته یک زوج مرتب مخصوص خودش داره که مولفه ی اول مکان x و مولفه ی دوم مکان y اونه. همونطور که میدونید حافظه به صورت خطیه ولی اینجا به خاطر راحت تر بودن محاسبات دو بعدی [به این صورت] شماره گذاری شده.
همچنین برای راحت تر شدن برنامه نویسی و افزایش سرعت، این thread ها در دسته های بزرگتری به نام block قرار گرفتند. هر block ،حافظه و همچنین شماره ی مخصوص خودش رو داره.
در اینجا برای راحت تر شدن کارمون از بلاک ها استفاده میکنیم. یعنی در واقع به کودا میگیم که بیا و خودت هسته ی مربوط به خودت رو توی بلاک پیدا کن. اینجوری اون حافظه ی مخصوص بلاک فقط به یک محاسبه اختصاص داده میشه. برگردیم به تابع خودمون و چگونگی اجراش رو روی این چهار هسته با هم ببینیم:

همونطور که در شکل پیداست هر بلاک تابع مخصوص خودش رو دریافت کرده. در واقع runtime برای هر بلاک یک کپی از تابع رو بر اساس شماره ی اون بلاک تهیه میکنه و روی اون بلاک به اجرا در میاره.

پس تا اینجا شما تقریبا با وظیفه ی runtime آشنا شدید : وظیفه ی runtime اینه  که کد مربوط به کارت گرافیک رو کامپایل کنه و به هر هسته توابع مخصوص به خودشون رو تحویل بده.
خب فکر کنم برای این قسمت کافی باشه. الآن دیگه میتونید دست به کار شید و چندتا برنامه‌ی ساده رو تمرین کنید. اگر با راه اندازی کودا روی سیستمتون مشکل دارید به این سایت یه سری بزنید : NVIDIA Developer Zone

در قسمت های بعدی بیشتر وارد دنیای کودا خواهیم شد.

۴,۱۴۳ total views, 2 views today

Print Friendly, PDF & Email

درباره ی سعید دادخواه

یه برنامه نویس !

همچنین ببینید

پردازش موازی قسمت اول

سلام دوستان. یه مقاله چند قسمتی در مورد برنامه نویسی و پردازش موازی و استفاده …

4
دیدگاه بگذارید

avatar
3 Comment threads
1 Thread replies
0 دنبال کنندگان
 
Most reacted comment
داغ ترین نخ نظرات
3 کامنت گذاران
amir00سعید دادخواهمحمد کامنت گذاران اخیر
  مشترک شو!  
جدیدترین قدیمی‌ترین دارای بیشترین امتیاز
میخوام باخبر شم از
محمد
Guest
محمد

سلام
الان خودمون thread بسازیم چه فرقی داره با این کودا؟

amir00
Member
amir00

بسیار عالی و جالب بود
 

amir00
Member
amir00

البته به نظر میرسه بیشتر برای کارهای حرفه ای خوبه
مثلا جاهایی که پردازش هامون به شکلی باشه که امکان اجرای اون با این شیوه باشه و همچنین سرعت پردازش خیلی برامون مهم باشه
بیشتر برنامه هایی که عموما نوشته میشن همین سرعت اجرای CPU براش کافی هست اما برای کارهای محاسباتی خیلی سنگین ارزش استفاده را داره