CLProgramCreate

소스 코드에서 OpenCL 프로그램을 생성합니다.

int  CLProgramCreate(
   int           context,     // OpenCL 컨텍스트 처리
   const string  source       // 소스 코드
   );

오버로드된 함수 버전은 OpenCL 프로그램을 생성하고 컴파일러 메시지를 전달된 문자열에 기록합니다.

int  CLProgramCreate(
   int           context,     // OpenCL 컨텍스트 처리
   const string  source,      // 소스 코드
   string       &build_log    // 컴파일 로그를 수신하기 위한 문자열
   );

Parameter

context

[in]  OpenCL 컨텍스트 처리.

source

[in]  OpenCL 프로그램의 소스 코드가 있는 문자열입니다.

&build_log

[in]  OpenCL 컴파일러 메시지를 수신하는 문자열.

반환값

성공한 경우 OpenCL 개체에 대한 핸들. 오류 발생 시 -1이 반환됩니다. 오류에 대한 자세한 내용은 GetLastError() 함수를 사용하십시오.

참고

현재 다음과 같은 오류 코드가 사용됩니다.

  • ERR_OPENCL_INVALID_HANDLE – 컨텍스트에 대한 잘못된 핸들 OpenCL.
  • ERR_INVALID_PARAMETER – 잘못된 문자열 매개 변수.
  • ERR_NOT_ENOUGH_MEMORY – 메모리가 부족하여 작업을 완료할 수 없음.
  • ERR_OPENCL_PROGRAM_CREATE – OpenCL의 내부 오류 또는 컴파일 오류.

일부 그래픽 카드에서는 기본적으로 double 유형 번호로 작업할 수 있습니다. 이로 인해 컴파일 오류 5105가 발생할 수 있습니다. double 유형 번호에 대한 지원을 활성화하려면 OpenCL 프로그램에 #pragma OPENCL EXTENSION cl_khr_fp64 : enable 명령을 추가하십시오.  그러나 그래픽 카드가 double을 지원하지 않는 경우 이 명령문을 활성화하는 것은 도움이 되지 않습니다.

예:

//+------------------------------------------------------------------+
//| OpenCL kernel                                                    |
//+------------------------------------------------------------------+
const string
cl_src=
       //--- 기본적으로 일부 GPU는 double을 지원하지 않습니다
       //--- cl_khr_fp64 명령어는 복수로 작업을 활성화하는 데 사용됩니다
       "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n"
       //--- OpenCL 커널 함수
       "__kernel void Test_GPU(__global double *data,      \r\n"
       "                       const    int N,             \r\n"
       "                       const    int total_arrays)  \r\n"
       "  {                                                \r\n"
       "   uint kernel_index=get_global_id(0);             \r\n"
       "   if (kernel_index>total_arrays) return;          \r\n"
       "   uint local_start_offset=kernel_index*N;         \r\n"
       "   for(int i=0; i<N; i++)                          \r\n"
       "     {                                             \r\n"
       "       data[i+local_start_offset] *= 2.0;          \r\n"
       "     }                                             \r\n"
       "  }                                                \r\n";
//+------------------------------------------------------------------+
//| Test_CPU                                                         |
//+------------------------------------------------------------------+
bool Test_CPU(double &data[],const int N,const int id,const int total_arrays)
  {
//--- 배열 사이즈 체크
   if(ArraySize(data)==0) return(false);
//--- 배열 인덱스 체크
   if(id>total_arrays) return(false);
//--- 인덱스 ID를 사용하여 배열의 로컬 오프셋 계산
   int local_start_offset=id*N;
//--- 요소에 2를 곱함
   for(int i=0; i<N; i++)
     {
      data[i+local_start_offset]*=2.0;
     }
   return true;
  }
//---
#define ARRAY_SIZE   100  // 배열의 크기
#define TOTAL_ARRAYS 5    // 총 배열
//--- OpenCL 핸들
int cl_ctx;  // OpenCL 컨텍스트 핸들
int cl_prg;  // OpenCL 프로그램 핸들
int cl_krn;  // OpenCL 커널 핸들
int cl_mem;  // OpenCL 버퍼 핸들
//---
double DataArray1[]; // CPU 연산을 위한 데이터 배열
double DataArray2[]; // GPU 연산을 위한 데이터 배열
//+------------------------------------------------------------------+
//| 스크립트 프로그램 시작 함수                                    |
//+------------------------------------------------------------------+
int OnStart()
  {
//--- OpenCL 개체 초기화
//--- OpenCL 컨텍스트 생성
   if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
     {
      Print("OpenCL을 찾을 수 없습니다. Error=",GetLastError());
      return(1);
     }
//--- OpenCL 프로그램 생성
   if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)
     {
      CLContextFree(cl_ctx);
      Print("OpenCL 프로그램 생성 실패. Error=",GetLastError());
      return(1);
     }
//--- OpenCL 커널 생성
   if((cl_krn=CLKernelCreate(cl_prg,"Test_GPU"))==INVALID_HANDLE)
     {
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL kernel 생성 실패. Error=",GetLastError());
      return(1);
     }
//--- OpenCL 버퍼 생성
   if((cl_mem=CLBufferCreate(cl_ctx,ARRAY_SIZE*TOTAL_ARRAYS*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)
     {
      CLKernelFree(cl_krn);
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("OpenCL 버퍼 생성 실패. Error=",GetLastError());
      return(1);
     }
//--- OpenCL 커널 상수 매개 변수 설정
   CLSetKernelArgMem(cl_krn,0,cl_mem);
   CLSetKernelArg(cl_krn,1,ARRAY_SIZE);
   CLSetKernelArg(cl_krn,2,TOTAL_ARRAYS);
//--- 데이터 배열 준비
   ArrayResize(DataArray1,ARRAY_SIZE*TOTAL_ARRAYS);
   ArrayResize(DataArray2,ARRAY_SIZE*TOTAL_ARRAYS);
//--- 배열에 데이터를 채웁니다
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- j번째 배열에 대한 로컬 시작 오프셋 계산
      uint local_offset=j*ARRAY_SIZE;
      //--- 인덱스 j로 배열 준비
      for(int i=0; i<ARRAY_SIZE; i++)
        {
         //--- MathCos(i+j) 함수로 배열을 채웁니다;
         DataArray1[i+local_offset]=MathCos(i+j);
         DataArray2[i+local_offset]=MathCos(i+j);
        }
     };
//--- CPU 연산 테스트
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- 인덱스 j를 사용하여 배열 계산
      Test_CPU(DataArray1,ARRAY_SIZE,j,TOTAL_ARRAYS);
     }
//--- CLExecute 매개변수 준비
   uint  offset[]={0};
//--- 전 세계 작업 규모
   uint  work[]={TOTAL_ARRAYS};
//--- OpenCL 버퍼에 데이터 쓰기
   CLBufferWrite(cl_mem,DataArray2);
//--- OpenCL 커널을 실행
   CLExecute(cl_krn,1,offset,work);
//--- OpenCL 버퍼에서 데이터 읽기
   CLBufferRead(cl_mem,DataArray2);
//--- 총 에러
   double total_error=0;
//--- 결과를 비교하고 오차를 계산
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- j번째 배열에 대한 로컬 오프셋 계산
      uint local_offset=j*ARRAY_SIZE;
      //--- 결과를 비교
      for(int i=0; i<ARRAY_SIZE; i++)
        {
         double v1=DataArray1[i+local_offset];
         double v2=DataArray2[i+local_offset];
         double delta=MathAbs(v2-v1);
         total_error+=delta;
         //--- 첫 번째 및 마지막 배열을 표시
         if((j==0) || (j==TOTAL_ARRAYS-1))
            PrintFormat("array %d of %d, element [%d]:  %f, %f, [error]=%f",j+1,TOTAL_ARRAYS,i,v1,v2,delta);
        }
     }
   PrintFormat("Total error: %f",total_error);
//--- OpenCL 개체 삭제
//--- free OpenCL 버퍼
   CLBufferFree(cl_mem);
//--- free OpenCL 커널
   CLKernelFree(cl_krn);
//--- free OpenCL 프로그램
   CLProgramFree(cl_prg);
//--- free OpenCL 컨텍스트
   CLContextFree(cl_ctx);
//---
   return(0);
  }