일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- Platform
- Device
- OpenCL 초기화
- Kernel
- Visual Leak Detector
- 메모리 누수
- Queue
- OpenCL 설치
- OpenCL 2.0 시작하기
- Intel OpenCL
- OpenCL
- initialize
- OpenCL 2.0
- program
- Memory Leak
- VLD
- init
- Today
- Total
후로링의 프로그래밍 이야기
#2 OpenCL 튜토리얼. OpenCL 인터페이스의 생성. 본문
OpenCL은 인터페이스입니다. 다시 말해 CPU와 GPU사이를 오가며 작업을 처리 해 줄 수 있게 도와주는 역활을 해줍니다. 아래 그림의 빨간색 선에 해당하는 것이 바로 OpenCL 인터페이스 입니다.
GPU를 사용하기위해서는 platform, device 포인터와 device를 이용해서 만드는 context 포인터 정보를 가지고 있어야 합니다. 그리고 device와 context를 이용해 실제 CL코드를 실행하는 queue에 대한 포인터를 를 생성해야 합니다.
각각이 무엇인지 확실히 이해를 하고 넘어가야 OpenCL이 실행되는 방식을 이해 할 수 있습니다.
Platform
만약 컴퓨터에 Interl CPU와 AMD GPU가 설치되어 있다면 선택 가능한 platform은 intel, amd입니다. 다시말해 platform이란 opencl서비스를 제공할 수 있는 환경을 말합니다. 플랫폼이 여러개 존재한다면 플랫폼을 한가지 선택해서 동작 시킬 수 있습니다. platform은 여러개 받을 수 있으며, 이렇게 처리한다면 이기종 컴퓨팅환경에서 다른 플랫폼의 디바이스 여러개를 동시에 사용 하는 것이 가능합니다.
OpenCL에서 Platform을 가져오는 과정은 다음과 같습니다.
현재 컴퓨터에 얼마나 많은 플랫폼이 있는지를 먼저 알아와야 합니다. 이후 플랫폼의 개수만큼 메모리를 할당하고 플랫폼을 얻어오게 됩니다.
1 2 3 4 | // get all platforms clGetPlatformIDs(0, NULL, &platformCount); platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * platformCount); clGetPlatformIDs(platformCount, platforms, NULL); | cs |
clGetPlatformIDs()를 이용해 플랫폼의 개수를 먼저 받아온 후에 platforms공간을 할당하고, 다시 clGetPlatformIDs()를 통해 플랫폼을 받아오게 됩니다.
Device
디바이스란 계산을 수행할수있는 유닛의 집합입니다. GPU로 설명하면 GPU내의 수많은 코어들의 집합이라고 이해하시면 될 것 같습니다. 플랫폼 내의 디바이스를 찾아 실제로 연산을 진행하게 됩니다.
1 2 3 4 | // 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, devices, NULL); | cs |
1 2 | //create context context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL); | cs |
1 2 | //create command queue queue = clCreateCommandQueue(context, device, 0, NULL); | cs |
Program
program이란 kernel의 집합이라고 보시면 됩니다. 간단하게 말해 프로그램 소스 혹은 빌드된 바이너리.
1 2 3 4 5 | // compile program program = clCreateProgramWithSource(context, 1, (const char**)&source, NULL, NULL); cl_int build_status; build_status = clBuildProgram(program, 1, &device, NULL, NULL, NULL); | cs |
1 2 | // 프로그램으로부터 커널 생성 simpleKernel = clCreateKernel(program, "simpleKernel", NULL); | cs |
OpenCL_Tutorial1_SumOfArray.zip
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | void CLInit() { int i, j; char* value; size_t valueSize; cl_uint platformCount; cl_platform_id* platforms; cl_uint deviceCount; cl_device_id* devices; cl_uint maxComputeUnits; // get all platforms clGetPlatformIDs(0, NULL, &platformCount); platforms = (cl_platform_id*)malloc(sizeof(cl_platform_id) * platformCount); clGetPlatformIDs(platformCount, platforms, NULL); for (i = 0; i < platformCount; i++) { // 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, devices, NULL); // for each device print critical attributes for (j = 0; j < deviceCount; j++) { // print device name clGetDeviceInfo(devices[j], CL_DEVICE_NAME, 0, NULL, &valueSize); value = (char*)malloc(valueSize); clGetDeviceInfo(devices[j], CL_DEVICE_NAME, valueSize, value, NULL); printf("platform %d. Device %d: %s\n", i + 1, j + 1, value); free(value); // print hardware device version clGetDeviceInfo(devices[j], CL_DEVICE_VERSION, 0, NULL, &valueSize); value = (char*)malloc(valueSize); clGetDeviceInfo(devices[j], CL_DEVICE_VERSION, valueSize, value, NULL); printf(" %d.%d Hardware version: %s\n", i + 1, 1, value); free(value); // print software driver version clGetDeviceInfo(devices[j], CL_DRIVER_VERSION, 0, NULL, &valueSize); value = (char*)malloc(valueSize); clGetDeviceInfo(devices[j], CL_DRIVER_VERSION, valueSize, value, NULL); printf(" %d.%d Software version: %s\n", i + 1, 2, value); free(value); // print c version supported by compiler for device clGetDeviceInfo(devices[j], CL_DEVICE_OPENCL_C_VERSION, 0, NULL, &valueSize); value = (char*)malloc(valueSize); clGetDeviceInfo(devices[j], CL_DEVICE_OPENCL_C_VERSION, valueSize, value, NULL); printf(" %d.%d OpenCL C version: %s\n", i + 1, 3, value); free(value); // print parallel compute units clGetDeviceInfo(devices[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(maxComputeUnits), &maxComputeUnits, NULL); printf(" %d.%d Parallel compute units: %d\n", i + 1, 4, maxComputeUnits); } } int platformNum; int deviceNum; printf("\n\n SELECT PLATFORM('1' ~ '%d') : ", platformCount); scanf("%d", &platformNum); printf("\n"); printf("SELECT DEVICE('1' ~ '%d') : ", deviceCount); scanf("%d", &deviceNum); printf("\n"); clGetDeviceIDs(platforms[platformNum - 1], CL_DEVICE_TYPE_ALL, deviceCount, devices, NULL); device = devices[deviceNum - 1]; // context 생성 context = clCreateContext(NULL, 1, &device, NULL, NULL, NULL); //create command queue queue = clCreateCommandQueue(context, device, 0, NULL); // 텍스트파일로부터 프로그램 읽기 char* source = readSource("convolution.cl"); // 프로그램 컴파일 및 빌드 program = clCreateProgramWithSource(context, 1, (const char**)&source, NULL, NULL); cl_int build_status; build_status = clBuildProgram(program, 1, &device, NULL, NULL, NULL); //프로그램으로부터 커널 포인터 생성 simpleKernel = clCreateKernel(program, "simpleKernel", NULL); } | cs |
다음 포스팅은 호스트에서 커널을 실행하는 방법과 커널 코드 작성법 입니다.
'OpenCL' 카테고리의 다른 글
#6 OpenCL 튜토리얼. Convolution Filter와 Local Memory 실습 (7) | 2016.12.20 |
---|---|
#5 OpenCL 튜토리얼. Convolution Filter와 Local Memory 이론 (1) | 2016.12.01 |
#4 OpenCL 튜토리얼. 이미지 프로세싱에 들어가기 전, 전체 워크플로우 학습 (1) | 2016.11.30 |
#3 OpenCL 튜토리얼. 버퍼의생성과 커널의실행. (3) | 2016.10.31 |
#1 OpenCL 설치하기. 간단한 설명. (8) | 2016.10.24 |