Notice
Recent Posts
Recent Comments
Today
Total
04-27 06:07
Archives
관리 메뉴

Jeongchul Kim

OpenCL[2] platform, device, context, command-queue, program 본문

OpenCL

OpenCL[2] platform, device, context, command-queue, program

김 정출 2018. 8. 21. 23:31

OpenCL platform, device, context, command-queue, program


OpenCL Reference

https://www.khronos.org/registry/cl/


기본 표준

- OpenCL 아키텍처(architecture) 대한 전반적인 설명

- Host program에서 사용하는 API 함수 설명(동작 방식, 파라미터(parameter), 리턴 값, 오류 코드 등)

- OpenCL 프로그램을 작성하기 위한 OpenCL C 언어 설명


OpenCL application execution process


OpenCL Host datatype

CL/cl_platform.h에 선언되어 있습니다.

cl_typename 타입 :  아키텍처마다 data type의 크기가 다를 수 있기 때문에 정의되어 있습니다.

cl_char 8 bit

cl_short 16 bit

cl_int 32 bit

cl_long 64 bit

cl_half 16 bit half-precision floating-point value

cl_float 32 bit single-precision floating-point value

cl_double 64 bit double-precision floating-point value


OpenCL의 data structure

CL/cl.h에 선언되어 있습니다. 내부적으로는 모두 포인터로 선언되어 있습니다.

- cl_platform_id

- cl_device_id

- cl_context

- cl_command_queue

- cl_program

- cl_kernel

- cl_mem

- cl_sampler

- cl_event


Platform and device

OpenCL 프레임워크마다 하나 이상의 플랫폼(platform)을 제공합니다.

시스템에 여러 vendor(AMD, Intel, NVIDIA)의 OpenCL 프레임워크가 설치되어 있으면, platform도 여러개 입니다.


Get platform id and number of platform

platform의 id와 개수를 가져옵니다.

cl_int clGetPlatformIDs (cl_uint num_entries, cl_platform_id *platforms, cl_uint *num_platforms)

리턴 값은 에러 정보를 의미합니다. 에러 코드별 의미는 CL/cl.h 파일에 정의되어 있습니다.


platform의 개수를 확인하고, platform id를 가져오는 코드는 다음과 같습니다.

cl_uint num_platforms;
cl_platform_id *platforms;

// Get number of platforms
err = clGetPlatformIDs(0, NULL, &num_platforms);
CHECK_ERROR(err);
printf("[*] Number of platforms : %d\n", num_platforms);

// Get platforms
platforms = (cl_platform_id*) malloc(sizeof(cl_platform_id) * num_platforms);
err = clGetPlatformIDs(num_platforms, platforms, NULL);
CHECK_ERROR(err);



Check Error

- CL_SUCCESS(0) 이면 성공입니다.

- 음수이면 실패입니다.


#define CHECK_ERROR(err) \
if(err != CL_SUCCESS) { \
printf("[%s $d] OpenCL error %d \n", \
__FILE__, __LINE__, err); \
exit(EXIT_FAILURE); \
}


Get platform Information

platform의 정보를 가져옵니다.


cl_int clGetPlatformInfo (cl_platform_id platform, cl_platform_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)


param_name: CL_PLATFORM_{PROFILE, VERSION}, CL_PLATFORM_{NAME, VENDOR, EXTENSIONS}, CL_PLATFORM_HOST_TIMER_RESOLUTION, CL_PLATFORM_ICD_SUFFIX_KHR [Table 4.1]

- CL_PLATFORM_NAME : platform 이름

- CL_PLATFORM_VENDOR : platform vendor 이름

- CL_PLATFORM_VERSION : platform이 지원하는 OpenCL 버전

- CL_PLATFORM_EXTENSIONS : platform이 지원하는 extension의 리스트


#define PLATFORM_NAME 256
#define PLATFORM_VENDOR 256
char platform_name[PLATFORM_NAME];
char platform_vendor[PLATFORM_VENDOR];

// Get platforms Info
cl_ushort platform_idx;
for(platform_idx = 0; platform_idx < num_platforms; platform_idx ++) {
   err = clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_NAME, sizeof(char) * PLATFORM_NAME, platform_name, NULL);
   CHECK_ERROR(err);
   err = clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_VENDOR, sizeof(char) * PLATFORM_VENDOR, platform_vendor, NULL);
   CHECK_ERROR(err);
   printf("[-] platform : %d\n", platform_idx);
   printf("CL_PLATFORM_NAME : %s\n", platform_name);
   printf("CL_PLATFORM_VENDOR : %s\n\n", platform_vendor);



Get Device ID and number of device

device와 ID와 개수를 가져옵니다.


cl_int clGetDeviceIDs (cl_platform_id platform, cl_device_type device_type, cl_uint num_entries, cl_device_id *devices, cl_uint *num_devices)


device_type: [Table 4.2] CL_DEVICE_TYPE_{ACCELERATOR, ALL, CPU}, CL_DEVICE_TYPE_{CUSTOM, DEFAULT, GPU}


device type에 ID를 얻어올 device의 종류를 지정해 줍니다.

- CL_DEVICE_TYPE_ALL

- CL_DEVICE_TYPE_CPU

- CL_DEVICE_TYPE_GPU

- CL_DEVICE_TYPE_ACCELERATOR : FPGA

- CL_DEVICE_TYPE_CUSTOM

- CL_DEVICE_TYPE_DEFAULT

- CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU


// Get number of devices
err = clGetDeviceIDs(platforms[platform_idx], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
CHECK_ERROR(err);

devices = (cl_device_id *)malloc(sizeof(cl_device_id) * num_devices);
err = clGetDeviceIDs(platforms[platform_idx], CL_DEVICE_TYPE_ALL, num_devices, devices, NULL);
CHECK_ERROR(err);
printf("[-] Number of devices : %d\n", num_devices);



Get device Information

device의 정보를 가져옵니다.


cl_int clGetDeviceInfo (cl_device_id device, cl_device_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)


param_name: [Table 4.3] CL_DEVICE_ADDRESS_BITS, CL_DEVICE_AVAILABLE, CL_DEVICE_BUILT_IN_KERNELS, CL_DEVICE_COMPILER_AVAILABLE, CL_DEVICE_{DOUBLE, HALF, SINGLE}_FP_CONFIG, CL_DEVICE_ENDIAN_LITTLE, CL_DEVICE_EXTENSIONS, CL_DEVICE_ERROR_CORRECTION_SUPPORT, CL_DEVICE_EXECUTION_CAPABILITIES, CL_DEVICE_GLOBAL_MEM_CACHE_{SIZE, TYPE}, CL_DEVICE_GLOBAL_MEM_{CACHELINE_SIZE, SIZE}, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE, CL_DEVICE_IL_VERSION, CL_DEVICE_IMAGE_MAX_{ARRAY, BUFFER}_SIZE, CL_DEVICE_IMAGE_SUPPORT, CL_DEVICE_IMAGE2D_MAX_{WIDTH, HEIGHT}, CL_DEVICE_IMAGE3D_MAX_{WIDTH, HEIGHT, DEPTH}, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, CL_DEVICE_LINKER_AVAILABLE, CL_DEVICE_LOCAL_MEM_{TYPE, SIZE}, …

param_name에 어떤 정보를 얻을 지 지정합니다.

- CL_DEVICE_NAME : device 이름

- CL_DEVICE_VENDOR : device vendor 이름

- CL_DEVICE_MAX_COMPUTE_UNITS : device의 CU 개수

- CL_DEVICE_MAX_WORK_GROUP_SiZE : work-group 하나의 work-item 개수 제한

- CL_DEVICE_GLOBAL_MEM_SIZE : global memory 크기

- CL_DEVICE_LOCAL_MEM_SIZE : local memory 크기

- CL_DEVICE_MAX_MEM_ALLOC_SIZE : memory object 크기 제한

- CL_DEVICE_HOST_UNIFIED_MEMORY : host와 device가 메모리를 공유하는지






#define DEVICE_NAME 256

char device_name[DEVICE_NAME];

// Get devices info
cl_ushort device_idx;
for(device_idx = 0; device_idx < num_devices; device_idx ++) {
   clGetDeviceInfo(devices[device_idx], CL_DEVICE_TYPE, sizeof(cl_device_type) , &device_type, NULL);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_NAME, sizeof(char) * DEVICE_NAME, device_name, NULL);
   CHECK_ERROR(err);



OpenCL ICD(Installable Client Driver)

동시에 여러 vendor의 platform을 얻어올 수 있습니다.

/etc/OpenCL/vendors 디렉터리 안에 시스템에 설치된 OpenCL 프레임워크들이 나열되어 있습니다.



OpenCL Context

kernel이 실행되는 환경입니다. 다른 객체들을 관리하기 위한 최상위 객체입니다.

context 단위로 command 간 동기화 및 메모리 관리르 수행합니다.

해당 context 안에서 사용할 device를 지정해야합니다. nvidia, amd 다른 platform은 context를 지정해야 합니다.


Create context


cl_context clCreateContext ( const cl_context_properties *properties, cl_uint num_devices, const cl_device_id *devices, void (CL_CALLBACK*pfn_notify) (const char *errinfo, const void *private_info, size_t cb, void *user_data), void *user_data, cl_int *errcode_ret)

properties: [Table 4.5] NULL or CL_CONTEXT_PLATFORM, CL_CONTEXT_INTEROP_USER_SYNC, CL_CONTEXT_{D3D10, D3D11}_DEVICE_KHR, CL_CONTEXT_ADAPTER_{D3D9, D3D9EX}_KHR, CL_CONTEXT_ADAPTER_DXVA_KHR, CL_CONTEXT_MEMORY_INITIALIZE_KHR, CL_CONTEXT_TERMINATE_KHR, CL_GL_CONTEXT_KHR, CL_CGL_SHAREGROUP_KHR, CL_{EGL, GLX}_DISPLAY_KHR, CL_WGL_HDC_KHR


2, 3번째 parameter가 유용


// Get platform
err = clGetPlatformIDs(1, &platform, NULL);
CHECK_ERROR(err);

// Get GPU device
err = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 1, &device, NULL);
CHECK_ERROR(err);

// Create context
context = clCreateContext(NULL, 1, &device, NULL, NULL, &err);
CHECK_ERROR(err);


한계

- 하나의 context에서 여러 platform의 device를 동시에 사용할 수 없습니다.

- device 사이에 데이터 복사, 동기화 등이 불가능합니다.


OpenCL Command-Queue

device마다 하나의 command-queue를 만들어 주어야 합니다.

하나의 device에 여러 개의 command-queue를 연결 할 수도 있습니다.


Create command_queue

cl_command_queue clCreateCommandQueueWithProperties ( cl_context context, cl_device_id device, const cl_command_queue_properties *properties, cl_int *errcode_ret)


*properties: Points to a zero-terminated list of properties and their values: [Table 5.1] CL_QUEUE_SIZE, CL_QUEUE_PROPERTIES (bitfield which may be set to an OR of CL_QUEUE_* where * may be: OUT_OF_ORDER_EXEC_MODE_ENABLE, PROFILING_ENABLE, ON_DEVICE[_DEFAULT]), CL_QUEUE_THROTTLE_{HIGH, MED, LOW}_KHR (requires the cl_khr_throttle_hint extension), CL_QUEUE_PRIORITY_KHR (bitfield which may be one of CL_QUEUE_PRIORITY_HIGH_KHR, CL_QUEUE_PRIORITY_MED_KHR, CL_QUEUE_PRIORITY_LOW_KHR (requires the cl_khr_priority_hints extension))


command_queue 종류

- In-order : command 들이 enqueue된 순서대로 실행합니다.

  > 앞의 커맨드가 끝나야 다음 커맨드가 시작됩니다.

  > 기본 실행 모드입니다.

  > gpu는 대부분 많이 사용합니다.


- out-of-order : command 들이 enqueue된 순서와 무관하게 실행합니다.

  > command의 사이의 순서를 맞춰주려면 별도의 동기화 기능 사용해야 합니다.

  > GPU에서는 순서만 변경될 뿐 병렬 처리가 되는 것은 아닙니다.

  > properties에 CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE을 지정해야 합니다.




cl_command_queue queues[2];

// Create command-queue
queues[0] = clCreateCommandQueue(context, devices[0], 0, &err);
CHECK_ERROR(err);

queues[1] = clCreateCommandQueue(context, devices[1], CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE, &err);
CHECK_ERROR(err);


OpenCL program object

OpenCL 프로그램의 binary

- IR(Intermediate Representation)일 수도 있고, device에서 실제 실행 가능한 코드일 수도 있습니다.

- 소스 코드를 입력을 준 다음 컴파일해서 실행 가능한 binary로 만들거나, 처음부터 binary를 입력으로 줄 수 있습니다.


소스 코드로부터 프로그램 오브젝트 만들기


cl_program clCreateProgramWithSource ( cl_context context, cl_uint count, const char **strings, const size_t *lengths, cl_int *errcode_ret)


const char *source_code = "..."
cl_context context;
cl_program program;

size_t source_size = strlen(source_code);
program = clCreateProgramWithSource(context, 1, &source_code, &source_size, &err);


이 방법은 잘 사용하지 않습니다.


대부분 kernel.cl 이라는 파일을 작성하고 읽어와 만듭니다.


char *get_source_code(const char *file_name, size_t *len) {
 char *source_code;
 size_t length;
 FILE *file = fopen(file_name, "r");
 if (file == NULL) {
   printf("[%s:%d] Failed to open %s\n", __FILE__, __LINE__, file_name);
   exit(EXIT_FAILURE);
 }

 fseek(file, 0, SEEK_END);
 length = (size_t)ftell(file);
 rewind(file);

 source_code = (char *)malloc(length + 1);
 fread(source_code, length, 1, file);
 source_code[length] = '\0';

 fclose(file);

 *len = length;
 return source_code;
}

// Get kernel code
kernel_source = get_source_code("kernel.cl", &kernel_source_size);

// Create program
program = clCreateProgramWithSource(context, 1, (const char**)&kernel_source,
   &kernel_source_size, &err);
CHECK_ERROR(err);



OpenCL program build

프로그램을 빌드(build) 합니다.


cl_int clBuildProgram (cl_program program, cl_uint num_devices, const cl_device_id *device_list, const char *options, void (CL_CALLBACK*pfn_notify) (cl_program program, void *user_data), void *user_data)


내부적으로 OpenCL 프레임워크의 OpenCL C 컴파일러 호출합니다.

컴파일을 수행할 device 리스트를 지정해주어야 합니다.

인자로 주어진 device 마다 각각 컴파일을 수행합니다.

빌드하지 않은 device에서는 kernel 실행이 불가합니다.


N이 정해져 있다면, -D N=1000


cl_device_id devices[4];
cl_program program;

err = clBuildProgram(program, 4, devices, "", NULL, NULL);
CHECK_ERROR(err);


Build options

-D name : 매크로 name을 1로 정의합니다.

-D name=definition  : 매크로 name을 definition으로 정의합니다.

-cl-opt-disable : 모든 컴파일러(compiler) 최적화를 끕니다.

-cl-unsafe-math-optimizations : 실수 연산의 에러 체크를 없애는 등의 방법으로 최적화를 합니다.

-cl-finite-math-only : 실수 값과 연산 결과가 NaN이나 무한대가 아니라고 가정합니다.


cl_device_id device;
cl_program program;

err = clBuildProgram(program, 1, &device, "-cl-fast-relaxed-math -w", NULL, NULL);

CHECK_ERROR(err);



cl_int clGetProgramBuildInfo ( cl_program program, cl_device_id device, cl_program_build_info param_name, size_t param_value_size, void *param_value, size_t *param_value_size_ret)


param_name: [Table 5.18] CL_PROGRAM_BINARY_TYPE, CL_PROGRAM_BUILD_{STATUS, OPTIONS, LOG}, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE


컴파일 에러 발생 시에 에러 메시지 확인으로 사용합니다.

특정 디바이스에 대해서 다른 컴파일을 수행하므로 하나의 device를 넣어 수행합니다.


// Build program
err = clBuildProgram(program, 1, &device, "", NULL, NULL);
if(err == CL_BUILD_PROGRAM_FAILURE) {
   size_t log_size;
   char *log;

   // Get program build
   err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
     0, NULL, &log_size);
   CHECK_ERROR(err);

   // Get build log
   log = (char*)malloc(log_size + 1);
   err = clGetProgramBuildInfo(program, device, CL_PROGRAM_BUILD_LOG,
     log_size, log, NULL);
   CHECK_ERROR(err);

   log[log_size] = '\0';
   printf("Compiler error : \n%s\n", log);
   free(log);
   exit(0);
}
CHECK_ERROR(err);



OpenCL kernel object



Kernel object를 앞에서 만든 프로그램 object에서 특정 kernel 함수만 분리합니다.

프로그램이 build된 다음에 만들어야 합니다.

나중에 kernel object를 사용해 kernel을 실행시킵니다.


cl_kernel clCreateKernel (cl_program program, const char *kernel_name, cl_int *errcode_ret)


// Build program
err = clBuildProgram(program, 1, &device, "", NULL, NULL);
CHECK_ERROR(err);

// Create kernel
kernel = clCreateKernel(program, "vec_add", &err);
CHECK_ERROR(err);


Reference Count

객체가 몇 군데서 참조되었는지 확인합니다.

Reference Count가 0이 되면 알아서 해당 객체가 저장된 메모리가 해제됩니다.

객체를 사용하는 중에는 reference count를 0보다 크게 유지해야합니다.


Reference count 증가 +1

- cl_int clRetainContext(cl_context context)

- cl_int clRetainCommandQueue(cl_command_queue command_queue)

- cl_int clRetainProgram(cl_program program)

- cl_int clRetainKernel(cl_kernel kernel)

- cl_int clRetainMemObject(cl_mem mem)


Reference count 감소 -1

- cl_int clReleaseContext(cl_context context)

- cl_int clReleaseCommandQueue(cl_command_queue command_queue)

- cl_int clReleaeseProgram(cl_program program)

- cl_int clReleaseKernel(cl_kernel kernel)

- cl_int clReleaseMemObject(cl_mem mem)


OpenCL Host program

host 코드 작성 시 cl.h 헤더 파일을 추가해야 합니다.

#include <CL/cl.h>


컴파일(링킹)

- 링킹 옵션에 -lOpenCL 추가합니다.

- 컴파일 예

 gcc -o opencl_app opencl_app.c -lOpenCL


OpenCL Github Code

밑에 있는 코드들은 다음의 github에 올려놓았습니다.

https://github.com/KimJeongChul/opencl





OpenCL Skeleton Code

#include <stdio.h>
#include <stdlib.h>
#include <CL/cl.h>

#define CHECK_ERROR(err) \
 if (err != CL_SUCCESS) { \
   printf("[%s:%d] OpenCL error %d\n", __FILE__, __LINE__, err); \
   exit(EXIT_FAILURE); \
 }

int main() {
 // TODO

 return 0;
}


Platform의 정보를 가져오는 코드입니다.

#include <stdio.h>
#include <stdlib.h>
#include <CL/cl.h>
#define PLATFORM_NAME 512
#define PLATFORM_VENDOR 256

#define CHECK_ERROR(err) \
 if (err != CL_SUCCESS) { \
   printf("[%s:%d] OpenCL error %d\n", __FILE__, __LINE__, err); \
   exit(EXIT_FAILURE); \
 }

int main() {
 // platform variables
 cl_uint num_platforms;
 cl_platform_id *platforms;
 char platform_name[PLATFORM_NAME];
 char platform_vendor[PLATFORM_VENDOR];
 cl_int err;

 // Get number of platforms
 clGetPlatformIDs(0, NULL, &num_platforms);
 

 // Get platforms
 platforms = (cl_platform_id*) malloc(sizeof(cl_platform_id) * num_platforms);
 clGetPlatformIDs(num_platforms, platforms, NULL);
 CHECK_ERROR(err);

 // Get platforms Info
 cl_ushort platform_idx;
 printf("Number of platforms : %d\n", num_platforms);
 for(platform_idx = 0; platform_idx < num_platforms; platform_idx ++) {
   clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_NAME, sizeof(char) * PLATFORM_NAME, platform_name, NULL);
   clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_VENDOR, sizeof(char) * PLATFORM_VENDOR, platform_vendor, NULL);
   printf("[*] platform : %d\n", platform_idx);
   printf("CL_PLATFORM_NAME : %s\n", platform_name);
   printf("CL_PLATFORM_VENDOR : %s\n", platform_vendor);
 }

 return 0;
}


$ gcc -o opencl_info opencl_info.c -lOpenCL

$ thorq --add --mode single --device gpu/7970 ./opencl_info


$ cat task_NUM.stdout



이번에는 디바이스 정보도 가져와보겠습니다.

$ vi opencl_info.c

#include <stdio.h>
#include <stdlib.h>
#include <CL/cl.h>
#define PLATFORM_NAME 256
#define PLATFORM_VENDOR 256
#define DEVICE_NAME 256


#define CHECK_ERROR(err) \
 if (err != CL_SUCCESS) { \
   printf("[%s:%d] OpenCL error %d\n", __FILE__, __LINE__, err); \
   exit(EXIT_FAILURE); \
 }

int main() {
 // platform variables
 cl_uint num_platforms;
 cl_platform_id *platforms;
 char platform_name[PLATFORM_NAME];
 char platform_vendor[PLATFORM_VENDOR];

 // device variables
 cl_uint num_devices;
 cl_device_id *devices;
 char device_name[DEVICE_NAME];
 cl_device_type device_type;
 cl_uint device_max_compute_units;
 size_t device_max_work_group_size;
 cl_ulong device_global_mem_size;
 cl_ulong device_local_mem_size;
 cl_ulong device_max_group_size;
 cl_ulong device_max_mem_alloc_size;
 cl_bool device_host_unified_memory;


 // error variable
 cl_int err;

 // Get number of platforms
 err = clGetPlatformIDs(0, NULL, &num_platforms);
 CHECK_ERROR(err);
 printf("[*] Number of platforms : %d\n", num_platforms);

 // Get platforms
 platforms = (cl_platform_id*) malloc(sizeof(cl_platform_id) * num_platforms);
 err = clGetPlatformIDs(num_platforms, platforms, NULL);
 CHECK_ERROR(err);

 // Get platforms Info
 cl_ushort platform_idx;
 for(platform_idx = 0; platform_idx < num_platforms; platform_idx ++) {
   err = clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_NAME, sizeof(char) * PLATFORM_NAME, platform_name, NULL);
   CHECK_ERROR(err);
   err = clGetPlatformInfo(platforms[platform_idx], CL_PLATFORM_VENDOR, sizeof(char) * PLATFORM_VENDOR, platform_vendor, NULL);
   CHECK_ERROR(err);
   printf("[-] platform : %d\n", platform_idx);
   printf("CL_PLATFORM_NAME : %s\n", platform_name);
   printf("CL_PLATFORM_VENDOR : %s\n\n", platform_vendor);

   // Get number of devices
   err = clGetDeviceIDs(platforms[platform_idx], CL_DEVICE_TYPE_ALL, 0, NULL, &num_devices);
   CHECK_ERROR(err);

   devices = (cl_device_id *)malloc(sizeof(cl_device_id) * num_devices);
   err = clGetDeviceIDs(platforms[platform_idx], CL_DEVICE_TYPE_ALL, num_devices, devices, NULL);
   CHECK_ERROR(err);
   printf("[-] Number of devices : %d\n", num_devices);

  // Get devices info
   cl_ushort device_idx;
  for(device_idx = 0; device_idx < num_devices; device_idx ++) {
   clGetDeviceInfo(devices[device_idx], CL_DEVICE_TYPE, sizeof(cl_device_type) , &device_type, NULL);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_NAME, sizeof(char) * DEVICE_NAME, device_name, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(cl_uint), &device_max_compute_units, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_MAX_WORK_GROUP_SIZE, sizeof(size_t), &device_max_group_size, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(cl_ulong), &device_max_group_size, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(cl_ulong), &device_local_mem_size, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(cl_ulong), &device_max_mem_alloc_size, NULL);
   CHECK_ERROR(err);
   err = clGetDeviceInfo(devices[device_idx], CL_DEVICE_HOST_UNIFIED_MEMORY, sizeof(cl_ulong), &device_host_unified_memory, NULL);
   CHECK_ERROR(err);
   printf("[*] device : %d\n", device_idx);
   if (device_type & CL_DEVICE_TYPE_CPU)
    printf("CL_DEVICE_TYPE : CL_DEVICE_TYPE_CPU\n");
   if (device_type & CL_DEVICE_TYPE_GPU)
    printf("CL_DEVICE_TYPE : CL_DEVICE_TYPE_GPU\n");
     printf("CL_DEVICE_NAME : %s\n", device_name);
     printf("CL_DEVICE_MAX_COMPUTE_UNITS : %d\n", device_max_compute_units);
     printf("CL_DEVICE_MAX_WORK_GROUP_SIZE : %d\n", device_max_work_group_size);
     printf("CL_DEVICE_GLOBAL_MEM_SIZE : %lu\n", device_max_group_size);
     printf("CL_DEVICE_LOCAL_MEM_SIZE : %lu\n", device_local_mem_size);
     printf("CL_DEVICE_MAX_MEM_ALLOC_SIZE : %lu\n", device_max_mem_alloc_size);
     printf("CL_DEVICE_HOST_UNIFIED_MEMORY : %lu\n\n", device_host_unified_memory);
   }

 }

 
 return 0;
}


$ gcc -o opencl_info opencl_info.c -lOpenCL

$ thorq --add --mode single --device gpu/7970 ./opencl_info

$ cat task_NUM.stdout


'OpenCL' 카테고리의 다른 글

OpenCL [0] introduction  (0) 2018.08.27
OpenCL[3] Memory Object, Kernel Execution  (0) 2018.08.23
OpenCL [1] concept  (0) 2018.08.21
Comments