جمعه 31 فروردین 1397 | Friday 20 th of April 2018 صفحه اصلی گروه الکترونیکی کامپیوتر
3-5-11- CUDA C

  CUDA Cشامل یکسری توسعه ها و یک کتابخانه زمان اجرا است که به استاندارد Cاضافه شده است. این در عمل برنامه نویسی دستگاه کودا با زبان Cرا فراهم می کند. توسعه های استاندارد Cاساسا برای تعریف و شروع کرنل ها و مدیریت حافظه است.

در ادامه توسعه های حافظه و کرنل از طریق یک برنامه ساده Cتوصیف شده اند، که شامل یک تابع اصلی و یک تابع جمع برداری است. این برنامه با زبان قراردادی Cبه کندی روی یک CPUاجرا شده است و برنامه CUDA Cکه شامل قسمت میزبان(تابع اصلی) و کرنل است روی یک دستگاه کودا اجرا شده است. پنج مرحله عمومی مدل برنامه برنامه نویسی کودا به اسانی می تواند در این مثال دیده شود.

مثال

 کد استاندارد C

//Function

void vectorSum(double *A, double *B, double *C)

{

C[0] = A[0] + B[0];

}

//Main program

int main()

{

//Vectors in the host memory

double *A, *B, *C;

/* Vector allocations (size N) in host memory */

/* Vector fills */

//Loop for function call

for (int i=0; i<N; i++) {

vectorSum(A+i, B+i, C+i);

}

/* Vector deallocations in host memory */

}

 کد CUDA

//Kernel

__global__ void vectorSum(double *A, double *B, double *C)

{

int thr_id = threadIdx.x;

C[idx] = A[idx] + B[idx];

}

14

//Main program

int main()

{

//Vectors in the host memory

double *A, *B, *C;

//Vectors in device memory

double *A_d, *B_d, *C_d;

/* Vector allocations (size N) in host memory */

/* Vector fills */

//Device memory allocations

cudaMalloc((void**) &A_d, sizeof(double)*N);

cudaMalloc((void**) &B_d, sizeof(double)*N);

cudaMalloc((void**) &C_d, sizeof(double)*N);

//Data transfer from host to device

cudaMemcpy(A_d, A, sizeof(double)*N, cudaMemcpyHostToDevice);

cudaMemcpy(B_d, B, sizeof(double)*N, cudaMemcpyHostToDevice);

//Kernel launch for vectors with N elements

vectorSum<<< 1, N >>>(A_d, B_d, C_d);

//Data transfer from device to host

cudaMemcpy(C, C_d, sizeof(double)*N, cudaMemcpyDeviceToHost);

//Device memory deallocations

cudaFree(A_d);

cudaFree(B_d);

cudaFree(C_d);

/* Vector deallocations in host memory */

}

کرنل ها

همانطور که پیش تر بیان شد قلب توسعه کودا در کرنل است. کرنل یک تابع زبان Cهمراه با بعضی تغییرات در رابطه با تعریف و فراخوانی و سازمان نخ ها است. تعریف کرنل شبیه تعریف یک تابع Cاست جز اینکه تعریف کننده اعلام (–global—) که کرنل دستگاه را تعریف می کند و باید از کد میزبان فراخوانی شود. تابع درون کرنل شبیه تابع Cاست. تنها فرق درون کرنل، متغیر است.

int thr id = threadIdx.x;

threadIdxیک متغیر ساخته شده است که اندیس نخ درون بلاک را می گوید. اندیس نخ بعنوان اندیس بردارها استفاده می شود به این شیوه هرنخ می داند که کدام المان استفاده شده است.

یک فراخوانی کرنل شامل یک نحو توسعه پیکربندی 1,Nاست. اینها تعداد نخ های اجرا شده و اینکه انها چگونه در بلاک مرتب شده اند را مشخص می کند. اولین مقدار در پیکربندی تعداد بلاک های نخ و دومین ان تعداد نخ های درون یک بلاک است. در این مثال فقط یک بلاک استفاده شده است و تعداد نخ ها اندازه بردارها است. تعداد بلاک ها و نخ ها می توانند در سه بعد نیز مشخص شوند( .xدر threadIdx).

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

int thrid = blockIdx.x * blockDim.x + threadIdx.x;

همانطور که گفته شد، threadIdxاندیس نخ درون بلاک است. بنابراین برای گرفتن اندیس نخ در کل کرنل افست بلاک کنونی باید تعیین شده باشد. که متغیرهای از پیش ساخته شده  blockIdx.xو  blockDim.xگرفته می شود. اینها اندیس این بلاک و تعداد نخ های درون یک بلاک هستند.

مدیریت حافظه

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

cudaMalloc((void**) &A d, sizeof(double)*N);

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

cudaFree(A d);

انتقال های حافظه بوسیله تابع زیر انجام می شود.

cudaMemcpy(A d, A, sizeof(double)*N, cudaMemcpyHostToDevice);

پارامترهای تابع، ادرس های حافظه مبدا و مقصد، اندازه انتقال ها برحسب بایت ها و جهت انتقال است.

Compatability by:
آخرین به روز رسانی سایت: سه شنبه, 22 اسفند 1391 - 00:26