CLProgramCreate

Cria um programa OpenCL a partir de um código fonte.

int  CLProgramCreate(
   int           context,     // Manipulador para um contexto OpenCL
   const string  source       // O código-fonte
   );

Parâmetros

context

[in]  Manipula o contexto OpenCL.

source

[in]  String com o código-fonte do programa OpenCL.

Valor do Retorno

Um manipulador para um objeto OpenCL se for bem sucedido. Em caso de erro é retornado -1. Para obter informações sobre o erro, utilize a função GetLastError().

Observação

Até o momento, são utilizados os seguintes códigos de erro:

  • ERR_OPENCL_INVALID_HANDLE — manipulador inválido para lidar com o OpenCL contexto.
  • ERR_INVALID_PARAMETER — parâmetro inválido de string.
  • ERR_NOT_ENOUGH_MEMORY — não há memória suficiente para concluir a operação.
  • ERR_OPENCL_PROGRAM_CREATE — erro interno do OpenCL ou erro de compilação.

Em alguns cartões gráficos, o trabalho com números do tipo double são desativados por padrão. Isso pode levar ao erro de compilação 5105. Para ativar o suporte para os números de tipo duplo, adicione a seguinte diretiva ao seu programa OpenCL: #pragma OPENCL EXTENSION cl_khr_fp64 : ativado

Exemplo:

//+------------------------------------------------------------------+
//| OpenCL kernel                                                    |
//+------------------------------------------------------------------+
const string
cl_src=
       //--- por padrão alguns GPUs não suportam doubles
       //--- a directiva cl_khr_fp64 é usada para habilitar o trabalho com doubles
       "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n"
       //--- função OpenCL kernel
       "__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)
  {
//--- checar tamanho do array
   if(ArraySize(data)==0) return(false);
//--- checar índice do array
   if(id>total_arrays) return(false);
//--- Calcular deslocamento local para o array com id do índice
   int local_start_offset=id*N;
//--- multiplicar elementos por 2
   for(int i=0; i<N; i++)
     {
      data[i+local_start_offset]*=2.0;
     }
   return true;
  }
//---
#define ARRAY_SIZE   100  // tamanho do array
#define TOTAL_ARRAYS 5    // total de arrays
//--- manipulador OpenCL
int cl_ctx;  // contexto do manipulador OpenCL
int cl_prg;  // programa do manipulador OpenCL
int cl_krn;  // Kernel do manipulador OpenCL
int cl_mem;  // buffer do manipulador OpenCL
//---
double DataArray1[]; // dados do array para cálculo do CPU
double DataArray2[]; // dados do array para cálculo do GPU
//+------------------------------------------------------------------+
//| Função de início do programa script                              |
//+------------------------------------------------------------------+
int OnStart()
  {
//--- inicializar objetos do OpenCL
//--- Criar contexto do OpenCL
   if((cl_ctx=CLContextCreate())==INVALID_HANDLE)
     {
      Print("OpenCL não encontrado. Error=",GetLastError());
      return(1);
     }
//--- criar programa OpenCL
   if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)
     {
      CLContextFree(cl_ctx);
      Print("criação programa OpenCL falhou. Error=",GetLastError());
      return(1);
     }
//--- criar kernel do OpenCL
   if((cl_krn=CLKernelCreate(cl_prg,"Test_GPU"))==INVALID_HANDLE)
     {
      CLProgramFree(cl_prg);
      CLContextFree(cl_ctx);
      Print("criação do kernel do OpenCL falhou. Error=",GetLastError());
      return(1);
     }
//--- criar buffer do 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("criação do buffer do OpenCL falhou. Error=",GetLastError());
      return(1);
     }
//--- Definir parâmetros de constante do kernel OpenCL
   CLSetKernelArgMem(cl_krn,0,cl_mem);
   CLSetKernelArg(cl_krn,1,ARRAY_SIZE);
   CLSetKernelArg(cl_krn,2,TOTAL_ARRAYS);
//--- preparar dados dos arrays
   ArrayResize(DataArray1,ARRAY_SIZE*TOTAL_ARRAYS);
   ArrayResize(DataArray2,ARRAY_SIZE*TOTAL_ARRAYS);
//--- preencher arrays com dados
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- Calcular o deslocamento de partida local para a jth array
      uint local_offset=j*ARRAY_SIZE;
      //--- preparar array com o índice j
      for(int i=0; i<ARRAY_SIZE; i++)
        {
         //--- Preencher arrays com funções MathCos(i+j);
         DataArray1[i+local_offset]=MathCos(i+j);
         DataArray2[i+local_offset]=MathCos(i+j);
        }
     };
//--- teste de cálculo do CPU
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- cálculo do array com o índice j
      Test_CPU(DataArray1,ARRAY_SIZE,j,TOTAL_ARRAYS);
     }
//--- preparar os parâmetros do CLExecute
   uint  offset[]={0};
//--- tamanho do trabalho global
   uint  work[]={TOTAL_ARRAYS};
//--- escrever dados para o buffer do OpenCL
   CLBufferWrite(cl_mem,DataArray2);
//--- executar kernel do OpenCL
   CLExecute(cl_krn,1,offset,work);
//--- Ler dados do buffer OpenCL
   CLBufferRead(cl_mem,DataArray2);
//--- total de erros
   double total_error=0;
//--- Comparar os resultados e calcular o erro
   for(int j=0; j<TOTAL_ARRAYS; j++)
     {
      //--- Calcular deslocamento local para o jth array
      uint local_offset=j*ARRAY_SIZE;
      //--- comparar os resultados
      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;
         //--- Mostrar primeiro e último arrays
         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);
//--- deletar objetos do OpenCL
//--- buffer OpenCL livre
   CLBufferFree(cl_mem);
//--- kernel OpenCL livre
   CLKernelFree(cl_krn);
//--- programa OpenCL livre
   CLProgramFree(cl_prg);
//--- contexto OpenCL livre
   CLContextFree(cl_ctx);
//---
   return(0);
  }