๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ก EE's DEV/FPGA

[OpenCL] OpenCL ํ”„๋กœ๊ทธ๋ž˜๋ฐ - 1 OpenCL ํ˜ธ์ŠคํŠธ์™€ ๋””๋ฐ”์ด์Šค

by Danna 2018. 8. 28.
728x90
728x90

1.1 OpenCL ํ”„๋กœ๊ทธ๋žจ ๊ตฌ์„ฑ
  • OpenCL๋กœ ํ”„๋กœ๊ทธ๋žจ์„ ๊ฐœ๋ฐœํ•  ๋•Œ๋Š” ๋””๋ฐ”์ด์Šค์—์„œ ๋™์ž‘ํ•˜๋Š” ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ๊ณผ ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์„ ๋”ฐ๋กœ ์ž‘์„ฑ
  • ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ[์ฝ”๋“œ 3-1] ์€ OpenCL C์–ธ์–ด๋กœ ์ž‘์„ฑ
  • ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ[์ฝ”๋“œ 3-2] ์€ C์–ธ์–ด๋กœ ์ž‘์„ฑํ•˜๋˜ OpenCL ๋Ÿฐํƒ€์ž„ API๋ฅผ ์‚ฌ์šฉ

1.2 ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ
__kernel void hello(__global char* string)
  • OpenCL C์–ธ์–ด ๋ฌธ๋ฒ•์— ๋งž์ถฐ ์ž‘์„ฑํ•œ๋‹ค.
  • hello() ํ•จ์ˆ˜์˜ ์„ ์–ธ์— ํ•จ์ˆ˜ ์ˆ˜์‹์ž __kernel์„ ์ง€์ • [C์–ธ์–ด์™€ ์ฐจ์ด์  1]
  • ํ•จ์ˆ˜ ์ˆ˜์‹์ž __kernel ์€ hello() ํ•จ์ˆ˜๊ฐ€ ๋””๋ฐ”์ด์Šค์—์„œ ๋™์ž‘ํ•˜๋ฉฐ ํ˜ธ์ŠคํŠธ์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋Š” ์ปค๋„ ํ•จ์ˆ˜์ž„์„ ์˜๋ฏธ.
  • __kernel ์ˆ˜์‹์ž๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ปค๋„ ํ•จ์ˆ˜๋Š” ๋‹ค์Œ 2๊ฐ€์ง€ OpenCL ๋Ÿฐํƒ€์ž„ API ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ํ˜ธ์ŠคํŠธ์—์„œ ํ˜ธ์ถœ ๊ฐ€๋Šฅ
    - ํƒœ์Šคํฌ ํ˜ธ์ถœ API ํ•จ์ˆ˜ : clEnqueueTask()
    - ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ ํ˜ธ์ถœ API ํ•จ์ˆ˜ : clEnqueueNDRangeKernel()
    - hello() ํ•จ์ˆ˜๋Š” ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ์„ ์œ„ํ•œ ํ•จ์ˆ˜๋Š” ์•„๋‹˜. ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์—์„œ clEnqueueTask ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ปค๋„์„ ํ˜ธ์ถœํ•จ.
  • hello() ํ•จ์ˆ˜์˜ ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ string์— ์ฃผ์†Œ ๊ณต๊ฐ„ ์ˆ˜์‹์ž __global์„ ์ง€์ • [C์–ธ์–ด์™€ ์ฐจ์ด์  2]
    - OpenCL ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ ์ค‘ ๊ธ€๋กœ๋ฒŒ ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•จ.
    - ์ผ๋ฐ˜์ ์œผ๋กœ ๋””๋ฐ”์ด์Šค ํ”„๋กœ๊ทธ๋žจ์€ OpenCL ๋ฉ”๋ชจ๋ฆฌ ๋ชจ๋ธ๋กœ ์ •์˜๋œ ๊ธ€๋กœ๋ฒŒ ๋ฉ”๋ชจ๋ฆฌ, ์ปจ์Šคํ„ดํŠธ ๋ฉ”๋ชจ๋ฆฌ, ๋กœ์ปฌ ๋ฉ”๋ชจ๋ฆฌ, ํ”„๋ผ์ด๋น— ๋ฉ”๋ชจ๋ฆฌ ์ค‘ ์–ด๋Š ํ•œ ๊ฐ€์ง€์— ์†ํ•œ๋‹ค.
    - ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ์ฝ๊ธฐ์™€ ์“ฐ๊ธฐ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฉฐ, ๊ฐ๊ฐ __global, __constant, __local, __private ์ด๋ผ๋Š” ์ˆ˜์‹์ž๋ฅผ ์ •์˜
    - ์ฃผ์†Œ ๊ณต๊ฐ„ ์ˆ˜์‹์ž๋ฅผ ์ƒ๋žตํ•˜๋ฉด __private์œผ๋กœ ์ง€์ •๋œ๋‹ค.

01 ์ปค๋„๋‚ด์—์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ช‡๋ฒˆ์งธ ์œ„์น˜์ธ์ง€ ํ™•์ธํ•˜๋Š” ๋ฐฉ๋ฒ•
  • get_global_size(0) : ๊ฐ€๋กœ ํฌ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • get_global_id(1) : ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ์œ„์น˜๊ฐ€ ์œ„์—์„œ๋ถ€ํ„ฐ ๋ช‡๋ฒˆ์งธ์— ์œ„์น˜ํ•ด ์žˆ๋Š”์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
  • get_global_id(0) : ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ์œ„์น˜๊ฐ€ ์™ผ์ชฝ์—์„œ๋ถ€ํ„ฐ ๋ช‡๋ฒˆ์งธ์— ์œ„์น˜ํ•ด ์žˆ๋Š”์ง€๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.


1.3 ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ
// OpenCL ์ปค๋„ ์‹คํ–‰
ret = clEnqueueTask(command_queue, kernel, 0, NULL, NULL);
  • OpenCL C์–ธ์–ด์˜ ๋ฌธ๋ฒ•์— ๋”ฐ๋ผ ๊ฐœ๋ฐœํ•œ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์€ OpenCL ๋Ÿฐํƒ€์ž„ API๋ฅผ ์ด์šฉํ•ด ๊ฐœ๋ฐœํ•œ ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์— ์˜ํ•ด ๋””๋ฐ”์ด์Šค์—์„œ ์‹คํ–‰๋œ๋‹ค.
  • ์ปค๋„ ํ•จ์ˆ˜ hello()๋ฅผ ํ˜ธ์ŠคํŠธ์—์„œ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ๋‹จ์ง€ OpenCL ๋Ÿฐํƒ€์ž„ API ํ•จ์ˆ˜์˜ ํ•˜๋‚˜์ธ clEnqueueTask()๋ฅผ ํ˜ธ์ถœํ•  ๋ฟ์ด๋‹ค. ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์ด๋ฅผ ์œ„ํ•ด ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์˜ ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์นœ๋‹ค.
  • ์ „์ฒด ์›Œํฌ ํ”Œ๋กœ์šฐ 
  1. ํ”Œ๋žซํผ ์ง€์ •
  2. ๋””๋ฐ”์ด์Šค ์„ ํƒ
  3. ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ (์„ ํƒ๋œ Device๋ฅผ ์ด์šฉํ•ด Context ์ƒ์„ฑ)
  4. ์ปค๋งจ๋“œ ํ ์ƒ์„ฑ
  5. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
  6. ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ ํŒŒ์ผ ์ฝ๊ธฐ
  7. ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
  8. ์ปค๋„ ์ปดํŒŒ์ผ
  9. ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
  10. ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
  11. ์ปค๋„ ์‹คํ–‰
  12. ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ ๋กœ๋“œ (Device๋กœ๋ถ€ํ„ฐ ์—ฐ์‚ฐ์ด ์™„๋ฃŒ๋œ Buffer Data ์ฝ๊ธฐ)
  13. ์˜ค๋ธŒ์ ํŠธ ํ•ด์ œ

01 ํ”Œ๋žซํผ ์ง€์ •

cl_platform_id platform_id = NULL;
...
cl_uint ret_num_platforms;
...
// ํ”Œ๋žซํผ, ๋””๋ฐ”์ด์Šค ์ •๋ณด๋ฅผ ์–ป์Œ
ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
  • OpenCL์˜ ํ”Œ๋žซํผ ๋ชจ๋ธ์€ ํ•˜๋‚˜์˜ ํ˜ธ์ŠคํŠธ์™€ ํ˜ธ์ŠคํŠธ์— ์—ฐ๊ฒฐ๋œ ํ•˜๋‚˜ ์ด์ƒ์˜ ๋””๋ฐ”์ด์Šค๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.
  • ๋”ฐ๋ผ์„œ ํ˜ธ์ŠคํŠธ์—์„œ OpenCL์„ ์ด์šฉํ•  ๋•Œ๋Š” ๊ฐ€์ • ๋จผ์ € ํ”„๋กœ๊ทธ๋žจ์ด ๋™์ž‘ํ•  OpenCL ํ”Œ๋žซํผ์„ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค.
  • clGetPlatformIDs()๋Š” OpenCL ๋Ÿฐํƒ€์ž„ API์— ์ •์˜๋œ ํ•จ์ˆ˜์ด๋ฉฐ, ์‹œ์Šคํ…œ์— ์กด์žฌํ•˜๋Š” ํ”Œ๋žซํผ ID๋ฅผ ์–ป๋Š”๋‹ค.
    - ์‹œ์Šคํ…œ์— OpenCL์ด ๋™์ž‘ํ•˜๋Š” ํ”Œ๋žซํผ(ํ•˜๋“œ์›จ์–ด)์ด ์กด์žฌํ•˜๋Š”์ง€ ์ฐพ์•„๋ณธ ํ›„,
    - ๊ฒ€์ƒ‰๋œ ํ”Œ๋žซํผ์ด ์žˆ์„ ๋•Œ cl_platform_id ํ˜•์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ platform_id์— ํ”Œ๋žซํผ ID๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
    - ์ดํ›„ ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์€ platform_id๋ฅผ ์ง€์ •ํ•ด ํ•ด๋‹น ํ”Œ๋žซํผ์„ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ํ˜ธ์ŠคํŠธ์— ์กด์žฌํ•˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์ด ์›ํ•˜๋Š” ํ”Œ๋žซํผ ์ˆ˜์ด๋ฉฐ ๋ณดํ†ต 1์„ ์ง€์ •ํ•œ๋‹ค.
  • ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ num_pltform์—๋Š” ์‹œ์Šคํ…œ์—์„œ ์‹ค์ œ๋กœ ์ด์šฉ ๊ฐ€๋Šฅํ•œ OpenCL ํ”Œ๋žซํผ ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

[์ฐธ๊ณ ] 01-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ํ”Œ๋žซํผ ์ง€์ •
static cl_platform_id platform = NULL;
...
// Get the OpenCL platform.
platform = findPlatform("Altera");
if (platform == NULL) {
    printf("ERROR: Unable to find Altera OpenCL platform.\n");
    return false;
}

[์ฐธ๊ณ ] 01-2 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
// get all platforms
clGetPlatformIDs(0, NULL, &platformCount);
platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * platformCount);
clGetPlatformIDs(platformCount, platforms, NULL);
  • platform์ด๋ž€ opencl ์„œ๋น„์Šค๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ๋งํ•œ๋‹ค.
  • ํ˜„์žฌ ์ปดํ“จํ„ฐ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ํ”Œ๋žซํผ์ด ์žˆ๋Š”์ง€๋ฅผ ๋จผ์ € ์•Œ์•„์™€์•ผ ํ•œ๋‹ค.
    - clGetPlatformIDs()๋ฅผ ์ด์šฉํ•ด ํ”Œ๋žซํผ์˜ ๊ฐœ์ˆ˜๋ฅผ platformCount์— ๋จผ์ € ๋ฐ›์•„์˜จ๋‹ค.
  • ์ดํ›„ ํ”Œ๋žซํผ์˜ ๊ฐœ์ˆ˜๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ• ๋‹นํ•˜๊ณ  ํ”Œ๋žซํผ์„ ์–ป์–ด์˜ค๊ฒŒ ๋œ๋‹ค.
    - platform ๋ณ€์ˆ˜ ๊ณต๊ฐ„์„ ํ• ๋‹นํ•˜๊ณ , clGetPlatformIDs()๋ฅผ ํ†ตํ•ด ํ”Œ๋žซํผ์„ ๋ฐ›์•„์˜จ๋‹ค.


02 ๋””๋ฐ”์ด์Šค ์„ ํƒ

cl_device_id device_id = NULL;
...
cl_uint ret_num_devices;
...
// ํ”Œ๋žซํผ, ๋””๋ฐ”์ด์Šค ์ •๋ณด๋ฅผ ์–ป์Œ
ret = clGetDeviceIDs(platform_id, CL_DEVICE_TYPE_DEFAULT, 1, &device_id, &ret_num_devices);
  • clGetDeviceIDs() ์—ญ์‹œ OpenCL ๋Ÿฐํƒ€์ž„ API์— ์ •์˜๋œ ํ•จ์ˆ˜์ด๋ฉฐ, ํ”Œ๋žซํผ์—์„œ ์ด์šฉ ๊ฐ€๋Šฅํ•œ ๋””๋ฐ”์ด์Šค๋ฅผ ์–ป๋Š”๋‹ค.
  • ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๋””๋ฐ”์ด์Šค๋ฅผ ์„ ํƒํ•˜๋ ค๋Š” ํ”Œ๋žซํผ์„ ์ง€์ •.
  • ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๋””๋ฐ”์ด์Šค์˜ ์ข…๋ฅ˜๋ฅผ ์ง€์ •. ํ•ด๋‹น ์˜ˆ์ œ๋Š” ํ”Œ๋žซํผ์ด ์ œ๊ณตํ•˜๋Š” ํ‘œ์ค€ ๋””๋ฐ”์ด์Šค๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” CL_DEVICE_TYPE_DEFAULT ๋ฅผ ์ง€์ •
  • ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์–ป์–ด์•ผ ํ•  ๋””๋ฐ”์ด์Šค์˜ ์ˆ˜๋ฅผ ์ง€์ •.
  • ๋„ค ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” device_id์— ์ €์žฅ๋œ ๋””๋ฐ”์ด์Šค๋ฅผ ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด์šฉํ•˜๊ธฐ ์œ„ํ•œ cl_device_id ํ˜•์˜ ๋””๋ฐ”์ด์Šค ํ•ธ๋“ค๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค. 
  • ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—์„œ ์ง€์ •ํ•œ ๋””๋ฐ”์ด์Šค๊ฐ€ ํ”Œ๋žซํผ์— ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ๋Š” ๋‹ค์„ฏ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ num_devices์— 0์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

[์ฐธ๊ณ ] 02-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋””๋ฐ”์ด์Šค ์„ ํƒ
static cl_device_id device = NULL;
...
// Query the available OpenCL devices.
scoped_array<cl_device_id> devices;
cl_uint num_devices;

devices.reset(getDevices(platform,CL_DEVICE_TYPE_ALL, &num_devices));

// We'll just use the first device.
device = devices[0];

[์ฐธ๊ณ ] 02-2 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
// get all devices
clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, 0, NULL, &deviceCount);
devices = (cl_device_id*)malloc(sizeof(cl_device_id) * deviceCount);
clGetDeviceIDs(platforms[i], CL_DEVICE_TYPE_ALL, deviceCount, device, NULL);
  • ๋””๋ฐ”์ด์Šค๋Š” ๊ณ„์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ๋‹›์˜ ์ง‘ํ•ฉ์ด๋‹ค.
  • GPU๋กœ ์„ค๋ช…ํ•˜์ž๋ฉด GPU๋‚ด์˜ ์ˆ˜๋งŽ์€ ์ฝ”์–ด๋“ค์˜ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ๋น„์œ ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ”Œ๋žซํผ ๋‚ด์˜ ๋””๋ฐ”์ด์Šค๋ฅผ ์ฐพ์•„ ์‹ค์ œ๋กœ ์—ฐ์‚ฐ์„ ์ง„ํ–‰ํ•˜๊ฒŒ ๋˜๋ฉฐ platform์„ ๋ฐ›์•„์˜ค๋Š” ๊ณผ์ •๊ณผ ๋™์ผํ•˜๋‹ค.


03 ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ

cl_context context = NULL;
...
// OpenCL ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ
context = clCreateContext(NULL, 1, &device_id, NULL, NULL, &ret);
  • ์ด์šฉํ•˜๋ ค๋Š” ๋””๋ฐ”์ด์Šค ํ•ธ๋“ค์„ ์–ป์—ˆ๋‹ค๋ฉด ๋‹ค์Œ์—๋Š” OpenCL ์‹คํ–‰ ํ™˜๊ฒฝ์ด ๋  OpenCL ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค. clCreateContext()๋Š” ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์ด๋‹ค.
  • ๋ณดํ†ต ์ปจํ…์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์ปค๋„์„ ์‹คํ–‰ํ•  ๋””๋ฐ”์ด์Šค๋ฅผ ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜ ์ด์ƒ ์ง€์ •ํ•ด์•ผ ํ•œ๋‹ค. 
    - ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ด์šฉํ•  ๋””๋ฐ”์ด์Šค์˜ ์ˆ˜๋ฅผ
    - ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ด์šฉํ•  ๋””๋ฐ”์ด์Šค์— ํ•ด๋‹น๋˜๋Š” ๋””๋ฐ”์ด์Šค ํ•ธ๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ง€์ •.
  • ์ดํ›„์— ์ƒ์„ฑ๋˜๋Š” ๊ฐ์ข… OpenCL ์˜ค๋ธŒ์ ํŠธ๋Š” ๋ชจ๋‘ ์—ฌ๊ธฐ์„œ ์ง€์ •ํ•œ OpenCL์˜ ์ปจํ…์ŠคํŠธ์— ์†ํ•˜๊ฒŒ ๋œ๋‹ค. ๊ฐ™์€ ์ปจํ…์ŠคํŠธ ์•ˆ์˜ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ†ตํ•ด์„œ ๊ฐ ๋””๋ฐ”์ด์Šค๋ฅผ ์ œ์–ดํ•œ๋‹ค.
  • ์ฆ‰, ์ปจํ…์ŠคํŠธ๋ž€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์—ฐ์‚ฐ ๋””๋ฐ”์ด์Šค๋ฅผ ์ด์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€์ƒ์˜ ์ปดํ“จํ„ฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์‰ฝ๋‹ค.

[์ฐธ๊ณ ] 03-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปจํ…์ŠคํŠธ ์ƒ์„ฑ
static cl_context context = NULL;
...
// Create the context.
context = clCreateContext(NULL, 1, &device, NULL, NULL, &status);
checkError(status, "Failed to create context");

[์ฐธ๊ณ ] 03-2 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
// create context
context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL);
  • CL ์ปค๋„์ด ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ์œผ๋กœ, ๋™๊ธฐํ™”์™€ ๋ฉ”๋ชจ๋ฆฌ ๊ด€๋ฆฌ๊ฐ€ ์ •์˜๋œ๋‹ค.
  • OpenCL๋””๋ฐ”์ด์Šค์—์„œ ์‹คํ–‰ํ•  OpenCLํ•จ์ˆ˜๋“ค์„ ํฌํ•จํ•˜๊ณ  ์žˆ๋‹ค.
  • clCreateContext()ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ƒ์„ฑํ•œ๋‹ค.


04 ์ปค๋งจ๋“œ ํ ์ƒ์„ฑ

cl_command_queue command_queue = NULL;
...
// ์ปค๋งจ๋“œ ํ ์ƒ์„ฑ
command_queue = clCreateCommandQueue(context, device_id, 0, &ret);
  • ๋””๋ฐ”์ด์Šค๋ฅผ ์ œ์–ดํ•˜๊ธฐ ์œ„ํ•œ ์ค€๋น„ ๊ณผ์ •
  • OpenCL์—์„œ๋Š” ํ˜ธ์ŠคํŠธ๊ฐ€ ๋””๋ฐ”์ด์Šค์—๊ฒŒ ๋ฌด์–ธ๊ฐ€๋ฅผ ์ง€์‹œ(์ปค๋„ ์‹คํ–‰ ๋ช…๋ น, ํ˜น์€ ํ˜ธ์ŠคํŠธ~๋””๋ฐ”์ด์Šค ์‚ฌ์ด์˜ ๋ฉ”๋ชจ๋ฆฌ ์ „์†ก ๋ช…๋ น)ํ•˜๋ ค๋ฉด ์ปค๋งจ๋“œ ํ ์˜ค๋ธŒ์ ํŠธ command_queue๋ฅผ ํ†ตํ•œ๋‹ค.
  • ๊ฐ๊ฐ์˜ ๋””๋ฐ”์ด์Šค์—๋Š” ๋ฐ˜๋“œ์‹œ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ปค๋งจ๋“œ ํ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • ํ•จ์ˆ˜๋Š” cl_command_queue ํ˜•์˜ ์ปค๋งจ๋“œ ํ ํ•ธ๋“ค์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ์ดํ›„ ์ปค๋„์„ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ํ˜ธ์ŠคํŠธ~๋””๋ฐ”์ด์Šค ์‚ฌ์ด์—์„œ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ „์†กํ•˜๋ ค๋ฉด ์ด ์ปค๋งจ๋“œ ํ ํ•ธ๋“ค์„ ์ง€์ •ํ•œ๋‹ค.
  • clCreateCommandQueue()๋Š” ์ปค๋งจ๋“œ ํ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์ด๋‹ค.
    - context : ์ปค๋งจ๋“œ ํ๊ฐ€ ์†Œ์†๋  ์ปจํ…์ŠคํŠธ
    - device_id : ์ปค๋งจ๋“œ ํ์˜ ๋ช…๋ น์„ ์‹คํ–‰ํ•  ๋””๋ฐ”์ด์Šค๋ฅผ ์ง€์ •

[์ฐธ๊ณ ] 04-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋งจ๋“œ ํ ์ƒ์„ฑ
static cl_command_queue queue = NULL;
...
// Create the command queue.
queue = clCreateCommandQueue(context, device, CL_QUEUE_PROFILING_ENABLE, &status);
checkError(status, "Failed to create command queue");

[์ฐธ๊ณ ] 04-2 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
// create command queue
queue = clCreateCommandQueue(context, device, 0, NULL);
  • ํ˜ธ์ŠคํŠธ์—์„œ ๋””๋ฐ”์ด์Šค ๋ณ„๋กœ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์œผ๋กœ ํ•˜๋‚˜์˜ ๋””๋ฐ”์ด์Šค์—์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ์ปค๋งจ๋“œ ํ๊ฐ€ ์—ฐ๊ฒฐ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์ปค๋งจ๋“œ ํ๋ฅผ ์ด์šฉํ•ด ์ปค๋„์„ ์‹คํ–‰ํ•˜๊ณ  ๋ฉ”๋ชจ๋ฆฌ์˜ ๋งคํ•‘, ์–ธ๋งคํ•‘, ๋™๊ธฐํ™” ๋“ฑ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.


05 ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ

cl_mem memobj = NULL;
...
// ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ ์ƒ์„ฑ
memobj = clCreateBuffer(context, CL_MEM_READ_WRITE, MEM_SIZE * sizeof(char), NULL, &ret);
  • ๋””๋ฐ”์ด์Šค์—์„œ ์ปค๋„์ด ๋™์ž‘ํ•  ๋•Œ ์ปค๋„์˜ ์ฒ˜๋ฆฌ ๋Œ€์ƒ์ธ ๋ฐฐ์—ด ๋“ฑ์˜ ๋ฐ์ดํ„ฐ๋Š” ๋ชจ๋‘ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์— ๋ฏธ๋ฆฌ ์ค€๋น„๋˜์–ด์•ผ ํ•˜๋ฉฐ, ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์— ์ฒ˜๋ฆฌํ•  ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•˜๋Š” ๊ฒƒ์€ ํ˜ธ์ŠคํŠธ์˜ ์—ญํ• ์ด๋‹ค.
  • ์ปค๋„ ์ž์ฒด๋Š” ๋””๋ฐ”์ด์Šค์˜ ์™ธ๋ถ€์— ์žˆ๋Š” ์ €์žฅ์žฅ์น˜๋‚˜ ๋„คํŠธ์›Œํฌ๋กœ๋ถ€ํ„ฐ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†๋‹ค. ๋”ฐ๋ผ์„œ ํ˜ธ์ŠคํŠธ๊ฐ€ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•  ๋•Œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค.
  • clCreateBuffer()๋Š” ๋””๋ฐ”์ด์Šค ์ƒ์— ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜์ด๋‹ค. ์—ฌ๊ธฐ์„œ ํ™•๋ณด๋œ ๋ฉ”๋ชจ๋ฆฌ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ memobj๋ฅผ ํ†ตํ•ด ํ˜ธ์ŠคํŠธ์—์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋‹ค.
    - context : ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์†Œ์†๋  ์ปจํ…์ŠคํŠธ๋ฅผ ์ง€์ •
    - CL_MEM_READ_WRITE : ๋ฉ”๋ชจ๋ฆฌ ์†์„ฑ, ์ปค๋„์ด ๋””๋ฐ”์ด์Šค ์ƒ์— ํ™•๋ณดํ•œ ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์— ๋ฐ์ดํ„ฐ ์ฝ๊ณ  ์“ฐ๊ธฐ ๊ฐ€๋Šฅ
    - MEM_SIZE * sizeof(char) : ํ™•๋ณดํ•  ๋ฉ”๋ชจ๋ฆฌ ํฌ๊ธฐ๋ฅผ ์ง€์ •

[์ฐธ๊ณ ] terasic example ์ค‘ hello๋Š” ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ , vector add๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํ„ฐ ์ƒ์„ฑ
scoped_array<cl_mem> input_a_buf; // num_devices elements
scoped_array<cl_mem> input_b_buf; // num_devices elements
scoped_array<cl_mem> output_buf; // num_devices elements
...
// Input buffers.
input_a_buf[i] = clCreateBuffer(context, CL_MEM_READ_ONLYn_per_device[i] * sizeof(float), NULL, &status);
checkError(status, "Failed to create buffer for input A");
input_b_buf[i] = clCreateBuffer(context, CL_MEM_READ_ONLY, n_per_device[i] * sizeof(float), NULL, &status);
checkError(status, "Failed to create buffer for input B");
// Output buffer.
output_buf[i] = clCreateBuffer(context, CL_MEM_WRITE_ONLYn_per_device[i] * sizeof(float), NULL, &status);
checkError(status, "Failed to create buffer for output");


06 ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ ํŒŒ์ผ ์ฝ๊ธฐ

FILE *fp;
char fileName[] = "./hello.cl";
char *source_str;
size_t source_size;
// ์ปค๋„์„ ํฌํ•จํ•œ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๋กœ๋“œ
fp = fopen(fileName, "r");
if (!fp)
{
        fprintf(stderr, "Failed to load kernel.\n");
        exit(1);
}
source_str = (char*)malloc(MAX_SOURCE_SIZE);
source_size = fread(source_str, 1, MAX_SOURCE_SIZE, fp);
fclose(fp);
  • ๋””๋ฐ”์ด์Šค์—์„œ ์ปค๋„์„ ์‹คํ–‰ํ•˜๋ ค๋ฉด ๋จผ์ € ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์„ ์ฝ์–ด๋“ค์ผ ํ•„์š”๊ฐ€ ์žˆ์œผ๋ฉฐ ์ด ์ž‘์—…์€ ํ˜ธ์ŠคํŠธ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ด๋ฃจ์–ด์ง„๋‹ค.
  • ์—ฌ๊ธฐ์„œ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์€ OpenCL ์ปดํŒŒ์ผ๋Ÿฌ๋กœ ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ ๋ฐ์ดํ„ฐ ํ˜น์€ ์ปดํŒŒ์ผํ•˜๊ธฐ ์ „์˜ ์†Œ์Šค ์ฝ”๋“œ ์ผ ์ˆ˜๋„ ์žˆ๋‹ค.
  • ์ปค๋„ ํŒŒ์ผ์„ ์ฝ์„ ๋•Œ๋Š” OpenCL ๋Ÿฐํƒ€์ž„ API๋ฅผ ์ด์šฉํ•˜์ง€ ์•Š๋Š”๋‹ค. 
  • fopen๊ณผ fread๋ฅผ ํ†ตํ•ด OpenCL C์–ธ์–ด์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ ์ฝ์–ด๋“ค์ธ๋‹ค.
  • ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์€ ํ†ต์ƒ์ ์œผ๋กœ ํ˜ธ์ŠคํŠธ์˜ ์ €์žฅ์žฅ์น˜์— ํŒŒ์ผ๋กœ ์กด์žฌํ•˜๋ฏ€๋กœ ๋‹ค์Œ์ฒ˜๋Ÿผ hello.cl ์„ ํ˜ธ์ŠคํŠธ์˜ ๋ฒ„ํผ์ธ source์— ์ฝ์–ด์˜จ๋‹ค.

[์ฐธ๊ณ ] 06-1 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
// ํ”„๋กœ๊ทธ๋žจ์œผ๋กœ๋ถ€ํ„ฐ ์ปค๋„ ์ƒ์„ฑ
simpleKernel = clCreateKernel(program, "simpleKernel"NULL);
  • kernel์˜ ์ง‘ํ•ฉ์ธ program ๋‚ด์—์„œ ํŠน์ • ์ปค๋„์„ ์„ ํƒํ•ด ์ปค๋„์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ์ปค๋„์„ ๋งŒ๋“ค๊ณ  ์ปค๋„์˜ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค. 


07 ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ

cl_program program = NULL;
...
// ๋ฏธ๋ฆฌ ๋กœ๋“œํ•œ ์†Œ์Šค ์ฝ”๋“œ๋กœ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์„ ์ƒ์„ฑ
program = clCreateProgramWithSource(context, 1, (const char **)&source_str, (const size_t *)&source_size, &ret);
  • ์œ„์™€ ๊ฐ™์€ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์˜ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๊ทธ๋Œ€๋กœ ์ปค๋„๋กœ ์ธ์‹์‹œํ‚ฌ ์ˆ˜ ์—†๋‹ค.
  • ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์—๋Š” ๋ณต์ˆ˜์˜ ์ปค๋„ ํ•จ์ˆ˜๊ฐ€ ํฌํ•จ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. 
  • OpenCL์—์„œ๋Š” ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์„ ๋จผ์ € ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋กœ ์ธ์‹์‹œ์ผœ์•ผ ํ•œ๋‹ค.
  • clCreateProgramWithSource()๋Š” ์†Œ์Šค ์ฝ”๋“œ๋กœ๋ถ€ํ„ฐ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋‹ค.
    (const char **)&source_str : ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์˜ ์†Œ์Šค ์ฝ”๋“œ
    (const size_t *)&source_size : ์†Œ์Šค ์ฝ”๋“œ์˜ ๋ฌธ์ž์—ด ํฌ๊ธฐ(๋ฐ”์ดํŠธ ๋‹จ์œ„)
  • ํ•ด๋‹น ํ•จ์ˆ˜๋Š” ์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์˜ ์†Œ์Šค ์ฝ”๋“œ ๋ฌธ์ž์—ด๋กœ๋ถ€ํ„ฐ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ์ธ program๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.
  • ๋ฏธ๋ฆฌ ์ปดํŒŒ์ผ๋œ ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ์˜ ๋ฐ”์ด๋„ˆ๋ฆฌ ํŒŒ์ผ์„ ๊ฐ€์ง€๊ณ  ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” clCreateProgramWithSource()ํ•จ์ˆ˜ ๋Œ€์‹  clCreateProgramWithBinary()ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.  

[์ฐธ๊ณ ] 07-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ ํŒŒ์ผ ์ฝ๊ณ  ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
cl_program program = NULL;
...
// Create the program.
std::string binary_file = getBoardBinaryFile("hello_world", device);
printf("Using AOCX: %s\n", binary_file.c_str());
program = createProgramFromBinary(context, binary_file.c_str(), device, num_devices);

[์ฐธ๊ณ ] 07-2 ํ›„๋กœ๋ฆฐ ๋ธ”๋กœ๊ทธ ์˜ˆ์ œ
program = clCreateProgramWithSource(context, 1, (const char **)&source, NULL, NULL);
cl_int build_status;
build_status = clBuildProgram(program, 1, &device, NULL, NULL, NULL);
  • program์ด๋ž€ kernel์˜ ์ง‘ํ•ฉ์ด๋ผ๊ณ  ๋ณด๋ฉด ๋œ๋‹ค.
  • ๊ฐ„๋‹จํžˆ ๋งํ•ด ํ”„๋กœ๊ทธ๋žจ ์†Œ์Šค ํ˜น์€ ๋นŒ๋“œ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ์ด๋‹ค.


08 ์ปค๋„ ์ปดํŒŒ์ผ

// ์ปค๋„ ํ”„๋กœ๊ทธ๋žจ ๋นŒ๋“œ
ret = clBuildProgram(program, 1, &device_id, NULL, NULL, NULL);
  • ์†Œ์Šค ์ฝ”๋“œ๋กœ ๋“ฑ๋กํ•œ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ OpenCL C ์ปดํŒŒ์ผ๋Ÿฌ์™€ ๋ง์ปค๋ฅผ ์‚ฌ์šฉํ•ด ๋นŒ๋“œํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.
  • clBuildProgram() ํ•จ์ˆ˜๋Š” OpenCL ์ปดํŒŒ์ผ๋Ÿฌ์™€ ๋ง์ปค์— ์˜ํ•ด ๋นŒ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
    - program : ๋นŒ๋“œ ๋Œ€์ƒ์ด ๋˜๋Š” ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ
    - ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ 1์€ ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์— ์ง€์ •ํ•œ ๋””๋ฐ”์ด์Šค ์ˆ˜
    - &device_id : ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ์— ์—ฐ๊ด€๋œ ๋””๋ฐ”์ด์Šค์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ
    - ๋„ค ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ๋„˜๊ฒจ์ค„ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฌธ์ž์—ด์„ ์ง€์ •ํ•œ๋‹ค.
  • ๋‹จ, ์ด ์ปดํŒŒ์ผ ์ ˆ์ฐจ๋Š” clCreateProgramWithSource() ํ•จ์ˆ˜์— ์˜ํ•ด ์†Œ์Šค ์ฝ”๋“œ๋กœ๋ถ€ํ„ฐ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ–ˆ์„ ๋•Œ๋งŒ ํ•„์š”ํ•˜๋‹ค. clCreateProgramWithBinary() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•ด ์ปดํŒŒ์ผ ๋œ ๋ฐ”์ด๋„ˆ๋ฆฌ๋กœ๋ถ€ํ„ฐ ์ง์ ‘ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ์ด ์ปดํŒŒ์ผ ์ ˆ์ฐจ๊ฐ€ ํ•„์š”์—†๋‹ค.

[์ฐธ๊ณ ] terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ์ปดํŒŒ์ผ
// Build the program that was just created.
status = clBuildProgram(program, 0, NULL, "", NULL, NULL);
checkError(status, "Failed to build program");


09 ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ

cl_kernel kernel = NULL;
...
// OpenCL ์ปค๋„ ์ƒ์„ฑ
kernel = clCreateKernel(program, "hello", &ret);
  • ์ปดํŒŒ์ผ๋œ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ–ˆ๋‹ค๋ฉด ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•ด์•ผ ํ•œ๋‹ค.
  • ํ•˜๋‚˜์˜ ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋Š” ํ•˜๋‚˜์˜ ์ปค๋„ ํ•จ์ˆ˜๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค. ๋”ฐ๋ผ์„œ ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋Š” ๋‹ค์Œ์ฒ˜๋Ÿผ ์ปค๋„ ํ•จ์ˆ˜ ์ด๋ฆ„์ธ hello๋ฅผ ์ง€์ •ํ•œ๋‹ค.
  • clCreateKernel() ํ•จ์ˆ˜๋Š” ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค.
    - ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ program : ์ปค๋„์„ ํฌํ•จํ•œ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ
    - ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ "hello" : ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋กœ ์ง€์ •ํ•œ ์ปค๋„ ํ•จ์ˆ˜ ์ด๋ฆ„
  • ์ด๋ฒˆ ์˜ˆ์—์„œ๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ์— ํ•˜๋‚˜์˜ ์ปค๋„ ํ•จ์ˆ˜๋งŒ์„ ์ƒ์„ฑํ–ˆ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋ณต์ˆ˜์˜ ์ปค๋„ ํ•จ์ˆ˜๋ฅผ ํ•˜๋‚˜์˜ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋กœ์„œ ์ƒ์„ฑํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 
  • ์ด๋Š” ํ•˜๋‚˜์˜ ํ”„๋กœ๊ทธ๋žจ ์˜ค๋ธŒ์ ํŠธ๋กœ๋ถ€ํ„ฐ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์˜๋ฏธ๋‹ค. ๋‹จ, ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ์™€ ์ปค๋„ ํ•จ์ˆ˜๋Š” 1๋Œ€1๋กœ ๋Œ€์‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— clCreateKernel() ํ•จ์ˆ˜๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ํ˜ธ์ถœํ•ด์•ผ ํ•œ๋‹ค.

[์ฐธ๊ณ ] terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ ์ƒ์„ฑ
// Create the kernel - name passed in here must match kernel name in the
// original CL file, that was compiled into an AOCX file using the AOC tool
const char *kernel_name = "hello_world" // Kernel name, as defined in the CL file
kernel = clCreateKernel(program, kernel_name, &status);
checkError(status, "Failed to create kernel");


10 ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •

// OpenCL ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
ret = clSetKernelArg(kernel, 0, sizeof(cl_mem), (void *)&memobj);
  • ์ปค๋„ ํ•จ์ˆ˜๊ฐ€ ์–ป๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ณผ์ •์ด๋‹ค.
  • ์ด๋ฒˆ ์˜ˆ์ œ์—์„œ๋Š” ๋ฌธ์ž์—ด ํ˜•์‹์˜ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ string์— ํ˜ธ์ŠคํŠธ์—์„œ ์ƒ์„ฑํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ memobj๋ฅผ ์ „๋‹ฌํ•œ๋‹ค. 
  • ์ด์ฒ˜๋Ÿผ ํ˜ธ์ŠคํŠธ์—์„œ ํ™•๋ณดํ•œ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌํ•  ๋•Œ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ฃผ์†Œ ๊ณต๊ฐ„ ์ˆ˜์‹์ž์ธ __global์„ ์ง€์ •ํ•ด ์„ ์–ธํ•œ๋‹ค.
  • clSetKernelArg() ํ•จ์ˆ˜๋Š” ์ปค๋„์— ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋‹ค.
    - ์ฒซ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ kernel : ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ปค๋„ ์˜ค๋ธŒ์ ํŠธ
    - ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ 0 : ๋„˜๊ฒจ์ค„ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ธ๋ฑ์Šค๋กœ์„œ ๋ฒ”์œ„๋Š” 0 ~ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ์ˆ˜-1,
    - ์ด๋ฒˆ ์˜ˆ์ œ๋Š” ์ฒซ ๋ฒˆ์งธ ๋ฌธ์ž์—ด ํ˜•์‹์˜ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ์ธ string์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— 0์„ ์ง€์ •ํ•จ. ๋”ฐ๋ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•  ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ์—ฌ๋Ÿฟ ์กด์žฌํ•œ๋‹ค๋ฉด ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ๊ฐ๊ฐ์„ clSetKernelArg() ํ•จ์ˆ˜๋กœ ํ˜ธ์ถœํ•œ๋‹ค.
    - ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ sizeof(cl_mem) : ๋„˜๊ฒจ์ค„ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ์ง€์ •
    - ๋„ค ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ (void *)&memobj : ์ „๋‹ฌํ•  ๋ฐ์ดํ„ฐ๋กœ ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ memobj๋ฅผ ์ง€์ •
  • ํ•ด๋‹น ์˜ˆ์ œ์—์„œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ง€์ •ํ–ˆ๋‹ค. ๋งŒ์•ฝ ํ˜ธ์ŠคํŠธ์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ง์ ‘ ์ „๋‹ฌํ•˜๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค.
int a = 10;
clSetKernelArg(kernel, 0, sizeof(int), (void *)&a);

[์ฐธ๊ณ ] terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
// Set the kernel argument (argument 0)
status = clSetKernelArg(kernel, 0, sizeof(cl_int), (void*)&thread_id_to_output);
checkError(status, "Failed to set kernel arg 0");

[์ฐธ๊ณ ] terasic vector example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •
// Set kernel arguments.
unsigned argi = 0;
status = clSetKernelArg(kernel[i], argi++, sizeof(cl_mem), &input_a_buf[i]);
checkError(status, "Failed to set argument %d", argi - 1);
status = clSetKernelArg(kernel[i], argi++, sizeof(cl_mem), &input_b_buf[i]);
checkError(status, "Failed to set argument %d", argi - 1);
status = clSetKernelArg(kernel[i], argi++, sizeof(cl_mem), &output_buf[i]);
checkError(status, "Failed to set argument %d", argi - 1);


11 ์ปค๋„ ์‹คํ–‰

// OpenCL ์ปค๋„ ์‹คํ–‰
ret = clEnqueueTask(command_queue, kernel, 0, NULL, NULL);
  • ์œ„์˜ ์ฝ”๋“œ๋Š” ํ˜ธ์ŠคํŠธ์—์„œ ๋””๋ฐ”์ด์Šค๋กœ ์ปค๋„์„ ์‹คํ–‰ํ•˜๋Š” ๊ณผ์ •, ๋””๋ฐ”์ด์Šค์—๊ฒŒ ํƒœ์Šคํฌ๋ฅผ ๋งก๊ธฐ๊ธฐ ์œ„ํ•ด ์ปค๋งจ๋“œ ํ์— ํƒœ์Šคํฌ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ตฌ๋ฌธ์ด๋‹ค.
  • hello๋ผ๋Š” ์ปค๋„์„ ์‹คํ–‰ํ•˜๋Š” ๋ช…๋ น์€ clEnqueueTask() ํ•จ์ˆ˜์— ์˜ํ•ด ํ์— ์ „๋‹ฌ๋œ ํ›„ ๋””๋ฐ”์ด์Šค ์ƒ์˜ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์—ฐ์‚ฐ ์œ ๋‹›์—์„œ ์‹คํ–‰ํ•œ๋‹ค.
  • clEnqueueTask() ํ•จ์ˆ˜๋Š” ์ปค๋งจ๋“œ ํ์— ๋ช…๋ น์„ ์ „๋‹ฌํ•  ๋ฟ์ด๋ฏ€๋กœ ํ˜ธ์ŠคํŠธ์—์„œ ํ˜ธ์ถœํ•œ clEnqueueTask() ํ•จ์ˆ˜์˜ ์‹คํ–‰์ด ๋๋‚œ ์‹œ์ ์—์„œ๋Š” hello๋ผ๋Š” ์ปค๋„์˜ ์‹คํ–‰์ด (๋””๋ฐ”์ด์Šค์—์„œ) ์ข…๋ฃŒ๋˜์—ˆ๋‹ค๊ณ  ๋ณด์žฅํ•  ์ˆ˜ ์—†๋‹ค.
  • clEnqueueTask() ํ•จ์ˆ˜๊ฐ€ ์ •์ƒ ์ข…๋ฃŒ๋˜์—ˆ์„ ๋•Œ๋Š” hello์˜ ์‹คํ–‰์„ ์˜๋ฏธํ•˜๋Š” ๋ช…๋ น์ด ์ปค๋งจ๋“œ ํ์— ์ œ๋Œ€๋กœ ์ „๋‹ฌ๋˜์—ˆ๋‹ค๋Š” ์ ๋งŒ ๋ณด์žฅํ•  ๋ฟ์ด๋‹ค. ์ฆ‰, ์‹ค์ œ๋กœ ๋””๋ฐ”์ด์Šค ์ƒ์—์„œ hello์˜ ์‹คํ–‰์ด ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋ ค๋ฉด ๋‹ค์„ฏ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ํ†ตํ•ด์„œ ์ด๋ฒคํŠธ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์–ป์–ด์•ผํ•œ๋‹ค.
  • clEnqueueTask() ํ•จ์ˆ˜๋Š” ํƒœ์Šคํฌ ๋ณ‘๋ ฌ์„ ์‹คํ–‰ํ•  ๋•Œ ์‚ฌ์šฉํ•œ๋‹ค. 
  • ๋ฐ์ดํ„ฐ ๋ณ‘๋ ฌ์„ ์‹คํ–‰ํ•  ๋•Œ๋Š” ์ธ๋ฑ์Šค ๊ณต์‚ฐ ์„ค์ •์„ ํ•„์š”๋กœ ํ•˜๋Š” clEnqueueNDRangeKernel() ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. -> ์•„๋ž˜ ์˜ˆ์ œ ์ฐธ๊ณ 

[์ฐธ๊ณ ] terasic vector example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์ปค๋„ ์‹คํ–‰
// Launch the kernel
status = clEnqueueNDRangeKernel(queue, kernel, 1, NULL, gSize, wgSize, 0, NULL, NULL);
checkError(status, "Failed to launch kernel");


12 ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ ๋กœ๋“œ

char string[MEM_SIZE];
...
// ์‹คํ–‰ ๊ฒฐ๊ณผ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ๋ฒ„ํผ์—์„œ ์–ป์Œ
ret = clEnqueueReadBuffer(command_queue, memobj, CL_TRUE, 0, MEM_SIZE * sizeof(char), string, 0, NULL, NULL);
  • ํ˜ธ์ŠคํŠธ์—์„œ ์ปค๋„์˜ ์ฒ˜๋ฆฌ ๊ฒฐ๊ณผ๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ๋””๋ฐ”์ด์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์—์„œ ํ˜ธ์ŠคํŠธ์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด์•ผ ํ•œ๋‹ค.
  • clEnqueueReadBuffer()๋Š” ๋””๋ฐ”์ด์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ˜ธ์ŠคํŠธ์˜ ๋ฉ”๋ชจ๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•˜๊ธฐ ์œ„ํ•œ ํ•จ์ˆ˜๋‹ค. ๋ฐ˜๋Œ€๋กœ ํ˜ธ์ŠคํŠธ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ๋””๋ฐ”์ด์Šค ๋ฉ”๋ชจ๋ฆฌ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ๋Š” clEnqueueWriteBuffer() ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•œ๋‹ค.
  • ํ•จ์ˆ˜ ์ด๋ฆ„์— 'Enqueue'๊ฐ€ ํฌํ•จ๋œ ๊ฒƒ์€ ๋””๋ฐ”์ด์Šค๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ํ•จ์ˆ˜์ธ ๊ฒƒ !!
  • clEnqueueReadBuffer() ํ•จ์ˆ˜๋Š” ์ปค๋งจ๋“œ ํ์— ๋ฉ”๋ชจ๋ฆฌ ๋ช…๋ น์ด ์ „๋‹ฌ๋œ ํ›„ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค.
    - ๋‘ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ memobj : ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์–ด๋“ค์ผ ๋””๋ฐ”์ด์Šค ์ƒ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ง€์ •
    - ์„ธ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ CL_TRUE : ๋™๊ธฐ ๋ฉ”๋ชจ๋ฆฌ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ฒ ๋‹ค๋Š” ๋œป, string์— ๋ณต์‚ฌ๊ฐ€ ๋๋‚  ๋•Œ๊นŒ์ง€ clEnqueueReadBuffer() ํ•จ์ˆ˜๋Š” ์ข…๋ฃŒ๋˜์ง€ ์•Š๋Š”๋‹ค. 
    -> ๋งŒ์•ฝ CL_FALSE๋ฅผ ์ง€์ •ํ•˜๋ฉด ๋น„๋™๊ธฐ ๋ฉ”๋ชจ๋ฆฌ ๋ณต์‚ฌ๋ฅผ ํ•˜๊ฒ ๋‹ค๋Š” ๋œป, ์ปค๋งจ๋“œ ํ์— ๋ณต์‚ฌ ๋ช…๋ น์ด ์ œ๋Œ€๋กœ ์ „๋‹ฌ๋˜๋ฉด ์‹ค์ œ ๋ฐ์ดํ„ฐ ๋ณต์‚ฌ๊ฐ€ ๋๋‚˜์ง€ ์•Š๋”๋ผ๋„ clEnqueueReadBuffer() ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ๋‹ค.
    - ๋‹ค์„ฏ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ MEM_SIZE * sizeof(char) : ๋ณต์‚ฌํ•  ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ(๋ฐ”์ดํŠธ)๋ฅผ ์ง€์ •
    - ์—ฌ์„ฏ ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ string : ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•  ํ˜ธ์ŠคํŠธ ์ƒ์˜ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ์ง€์ •
  • ํ˜ธ์ŠคํŠธ์—์„œ clEnqueueReadBuffer() ํ•จ์ˆ˜์—๊ฒŒ ๋””๋ฐ”์ด์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ์œผ๋ผ๋Š” ์ง€์‹œ๋ฅผ ๋‚ด๋ฆฌ๊ธฐ ์ „, hello ์ปค๋„์ด ๋ฐ˜๋“œ์‹œ ์ข…๋ฃŒ๋˜์—ˆ๋‹ค๊ณ  ํ•  ์ˆ˜ ์žˆ์„๊นŒ? ์— ๋Œ€ํ•œ ์งˆ๋ฌธ
    - ํ˜ธ์ŠคํŠธ์˜ ์ปค๋„ ์‹คํ–‰ ํ•จ์ˆ˜ clEnqueueTask()๋Š” ํ์— ์ „๋‹ฌ๋œ ์ง€์ ์—์„œ ๋น ์ ธ๋‚˜์˜จ๋‹ค.
    - ์ปค๋„์˜ ์‹คํ–‰์ด ๋๋‚˜๊ธฐ ์ „์— ๋””๋ฐ”์ด์Šค์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฝ๋Š”๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ์ƒ๊ธธ ์ˆ˜ ์žˆ์ง€๋งŒ Enqueue ๊ณ„์—ด์˜ ํ•จ์ˆ˜๋Š” ํ˜ธ์ŠคํŠธ์—์„œ ๋ณด๋ฉด ๋น„๋™๊ธฐ ํ˜ธ์ถœ์ด์ง€๋งŒ ์ปค๋งจ๋“œ ํ์— ํˆฌ์ž…๋œ ๋ช…๋ น์˜ ์‹คํ–‰ ์ˆœ์„œ๋Š” ์ปค๋งจ๋“œ ํ ์ƒ์„ฑ์‹œ ํŠน๋ณ„ํ•œ ์ง€์ •์„ ํ•˜์ง€ ์•Š๋Š” ์ด์ƒ ๋™๊ธฐ ์‹คํ–‰(ํ์— ์ „๋‹ฌ๋œ ์ˆœ์„œ๋Œ€๋กœ ๋ช…๋ น์„ ์‹คํ–‰)์ด๋ฏ€๋กœ ์šฐ๋ คํ•  ํ•„์š” ์—†๋‹ค.
    - ์ด๋ฒˆ ์˜ˆ๋Š” ์ปค๋งจ๋“œ ํ์— ๋น„๋™๊ธฐ ์‹คํ–‰ ์ง€์‹œ๋ฅผ ๋‚ด๋ฆฌ์ง€ ์•Š์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋จผ์ € ํ์— ์ „๋‹ฌ๋œ ์ปค๋„ ์‹คํ–‰ ๋ช…๋ น์ด ์ข…๋ฃŒ๋œ ๊ฒƒ์„ ํ™•์ธํ•œ ํ›„ ๋ฉ”๋ชจ๋ฆฌ ๋ณต์‚ฌ ๋ช…๋ น์ด ์‹คํ–‰๋œ๋‹ค.

[์ฐธ๊ณ ] terasic hello example ์—์„œ๋Š” ์ฝ์„ ๊ฒƒ์ด ์—†์Œ
[์ฐธ๊ณ ] terasic vector example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋ฉ”๋ชจ๋ฆฌ ์˜ค๋ธŒ์ ํŠธ ๋กœ๋“œ
// Read the result. This the final operation.
status = clEnqueueReadBuffer(queue[i], output_buf[i], CL_FALSE0, n_per_device[i] * sizeof(float), output[i], 1, &kernel_event[i], &finish_event[i]);


13 ์˜ค๋ธŒ์ ํŠธ ํ•ด์ œ

ret = clReleaseKernel(kernel);
ret = clReleaseProgram(program);
ret = clReleaseMemObject(memobj);
ret = clReleaseCommandQueue(command_queue);
ret = clReleaseContext(context);
  • ํ”„๋กœ๊ทธ๋žจ์˜ ์•ˆ์ „ํ•œ ์ข…๋ฃŒ๋ฅผ ์œ„ํ•ด ์ƒ์„ฑํ•œ ๊ฐ์ข… ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ•ด์ œํ•ด์•ผ ํ•œ๋‹ค. 
  • ์‚ฌ์šฉ์ด ๋๋‚œ ์˜ค๋ธŒ์ ํŠธ๋Š” ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ƒ์„ฑ๊ณผ ํ•ด์ œ๋ฅผ ๋งค๋ฒˆ ์‹ค์‹œํ•  ํ•„์š”๋Š” ์—†๋‹ค.
  • ์‹ค์ œ ํ”„๋กœ๊ทธ๋žจ์—์„œ๋Š” ์ปค๋„ ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์„ค์ • ํ˜น์€ ์ž…๋ ฅ ๋ฒ„ํผ๋ฅผ ํ†ตํ•ด ๋ฉ”๋ชจ๋ฆฌ ๋ณต์‚ฌ -> ์ปค๋„ ์‹คํ–‰ -> ๋ฉ”๋ชจ๋ฆฌ ์ฝ๊ธฐ๋ฅผ ๋ฐ˜๋ณตํ•˜๋Š” ๊ฒƒ์ด ๊ธฐ๋ณธ์ด๋‹ค.
  • ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ƒ์„ฑ๋งŒ ํ•˜๊ณ  ํ•ด์ œ์‹œํ‚ค์ง€ ์•Š์œผ๋ฉด์„œ ๊ณ„์† ์‚ฌ์šฉํ•˜๋ฉด ํ˜ธ์ŠคํŠธ์˜ ๊ฐ์ข… ์˜ค๋ธŒ์ ํŠธ ๊ด€๋ฆฌ์šฉ ๋ฉ”๋ชจ๋ฆฌ ์˜์—ญ์ด ๋ถ€์กฑํ•ด์ง„๋‹ค. ์ด ๋•Œ๋Š” OpenCL ๋Ÿฐํƒ€์ž„์ด ๋ฉ”๋ชจ๋ฆฌ ๋ถ€์กฑ ์—๋Ÿฌ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

[์ฐธ๊ณ ] 13-1 terasic hello example ์—์„œ๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ์˜ค๋ธŒ์ ํŠธ ํ•ด์ œ
// Free the resources allocated during initialization
void cleanup() {
        if (kernel) {
               clReleaseKernel(kernel);
        }
        if (program) {
               clReleaseProgram(program);
        }
        if (queue) {
               clReleaseCommandQueue(queue);
        }
        if (context) {
               clReleaseContext(context);
        }
}

728x90
728x90

'๐Ÿ’ก EE's DEV > FPGA' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[OpenCL] VS 2017์—์„œ OpenCL ์‚ฌ์šฉํ•˜๊ธฐ  (0) 2018.08.08
[FPGA] NIOS II Tutorial Helloworld  (0) 2018.08.08