Frist OpenCL example on Windows

이제 OpenCL 예제 프로그램을 작성하여 보자.

작성하기전 알아야 될 개념은 OpenCL은 가용한 자원들의 집합이 추상화된 platform과 platform안에 연산유닛이 추상화된 device라는 개념이 있다.

가용한 platform은 OpenCL에서 사용할수 있도록 알맞은 드라이버가 설치되어 있어야한다.


  • NVidia 그래픽 카드의 경우 CUDA를 설치하면 드라이버가 설치된다.
  • Intel CPU의 경우는 intel opencl 로 구글링하면 "Intel Developer zone" 이 리스팅되는데 이곳(https://software.intel.com/en-us/articles/opencl-drivers)에서 본인에게 알맞은 드라이버를 다운로드 하면 CPU자원을 이용할 수 있다.

실제 C로 작성되는 프로그램은 host 라고 부르며, 병렬로 처리되는 함수를 kernel이라고 한다. kernel은 C언어에 OpenCL의 예약어를 이용하여 작성할 수 있다.

성격 급하니 이론보다 코딩부터 해보자.

먼저 내가 사용할 수 있는 연산자원이 얼마나 있는지 확인하여 보자.
(예제 프로그램은 구글링한 결과를 참고하여 작성하였다. - 출처불명)

host 프로그램 예제(getinfo.c)

#include <stdio.h>
#include <stdlib.h>

#include <CL/cl.h>


int main()

{

 unsigned int i, j;   

        //플랫폼을 가져오기 위한 배열(실제로는 포인터사용후 메모리 할당 해야함)
 cl_platform_id platforms[32]; 
     
        // 플랫폼의 갯수를 저장하기위한 변수
 cl_uint num_platforms;  

        // 벤더이름. 1024바이트를 넘지 않았으면 한다. 
 char vendor[1024];    

        //디바이스를 가져오기 위한 배열(실제로는 포인터사용후 메모리 할당 해야함)
 cl_device_id devices[32];

        // 디바이스 갯수를 저장하기 위한 변수
 cl_uint num_devices;

        // 디바이스이름. 1024바이트를 넘지 않았으면 한다. 
 char deviceName[1024];

 cl_uint numberOfCores; 
 cl_long amountOfMemory; 
 cl_uint clockFreq; 
 cl_ulong maxAlocatableMem; 
 cl_ulong localMem;  
 cl_bool available;  
 

 clGetPlatformIDs (32, platforms, &num_platforms);
        printf("\nNumber of platforms:\t%u\n\n", num_platforms);

 
 //플랫폼 수만큼 루프

 for(i = 0; i < num_platforms; i++)

 {

  printf("Platform:\t\t%u\n\n", i);

  clGetPlatformInfo (platforms[i], CL_PLATFORM_VENDOR, sizeof(vendor), vendor, NULL);

  printf("\tPlatform Vendor:\t%s\n", vendor);

  

  clGetDeviceIDs (platforms[i], CL_DEVICE_TYPE_ALL, sizeof(devices), devices, &num_devices);

  printf("\tNumber of devices:\t%u\n\n", num_devices);

  // 디바이스 루프
  for(j = 0; j < num_devices; j++)

  {
   // 디바이스 정보

   clGetDeviceInfo(devices[j], CL_DEVICE_NAME, sizeof(deviceName), deviceName, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_VENDOR, sizeof(vendor), vendor, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_MAX_COMPUTE_UNITS, sizeof(numberOfCores), &numberOfCores, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_GLOBAL_MEM_SIZE, sizeof(amountOfMemory), &amountOfMemory, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_MAX_CLOCK_FREQUENCY, sizeof(clockFreq), &clockFreq, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_MAX_MEM_ALLOC_SIZE, sizeof(maxAlocatableMem), &maxAlocatableMem, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_LOCAL_MEM_SIZE, sizeof(localMem), &localMem, NULL);
   clGetDeviceInfo(devices[j], CL_DEVICE_AVAILABLE, sizeof(available), &available, NULL);

   printf("\tDevice: %u\n", j);

   printf("\t\tName:\t\t\t\t%s\n", deviceName);

   printf("\t\tVendor:\t\t\t\t%s\n", vendor);

   printf("\t\tAvailable:\t\t\t%s\n", available ? "Yes" : "No");

   printf("\t\tCompute Units:\t\t\t%u\n", numberOfCores);

   printf("\t\tClock Frequency:\t\t%u mHz\n", clockFreq);

   printf("\t\tGlobal Memory:\t\t\t%0.00f mb\n", (double)amountOfMemory/1048576);

   printf("\t\tMax Allocateable Memory:\t%0.00f mb\n", (double)maxAlocatableMem/1048576);

   printf("\t\tLocal Memory:\t\t\t%u kb\n\n", (unsigned int)localMem);

  }

 }

 return 0;

}

컴파일 후 실행하여 보자.
혹시 초보분들을 위해.. 쉽게 설명하자면 opencl 라이브러리와 헤더위치를 지정해주어야 하는데
LD_LIBRARY_PATH, LIBRARY_PATH를 CUDA path 아래 로 지정해 주면 된다.
잘 모르겠다면 C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v6.5 아래에서 그냥 복사해오면된다.
지금 목적은 platform과 device정보 출력이니 컴파일시 필요한 라이브러리 패스 와 make 등은 구글링해보자
gcc getinfo.c -o getinfo -lOpenCL
$ getinfo

Number of platforms:    2

Platform:               0

        Platform Vendor:        NVIDIA Corporation
        Number of devices:      1

        Device: 0
                Name:                           GeForce 8400 GS
                Vendor:                         NVIDIA Corporation
                Available:                      Yes
                Compute Units:                  2
                Clock Frequency:                918 mHz
                Global Memory:                  256 mb
                Max Allocateable Memory:        128 mb
                Local Memory:                   16383 kb

Platform:               1

        Platform Vendor:        Intel(R) Corporation
        Number of devices:      1

        Device: 0
                Name:                           Intel(R) Core(TM)2 CPU 6400  @ 2.13GHz
                Vendor:                         Intel(R) Corporation
                Available:                      Yes
                Compute Units:                  2
                Clock Frequency:                2130 mHz
                Global Memory:                  2048 mb
                Max Allocateable Memory:        512 mb
                Local Memory:                   32768 kb


dh@dhpc ~/src
$

GeForcec 8400 GS 가 detect 되었고, 연산 유닛이 2개이다.
마찬가지로 Intel Core 2 CPU가 detect 되었고 연산 유닛이 2개이다.

오래된 내 컴퓨터도 이종 병렬 프로그래밍이 가능한걸 알수 있다.

댓글

이 블로그의 인기 게시물

C#에서 포인터 사용

WPF RichTextBox 와 Document의 바인딩

WPF Template에 Grid 사용하기( UniformGrid, Grid, WrapPanel)