CLBufferRead

Lê um buffer de OpenCL em uma array e retorna o número de elementos de leitura.

uint  CLBufferRead(
   int          buffer,                    // Um manipulador para o buffer OpenCL
   const void&  data[],                    // Uma array de valores
   uint         buffer_offset=0,           // Um deslocamento no buffer OpenCL em bites, 0 por padrão
   uint         data_offset=0,             // Um deslocamento na array de elementos, 0 por padrão
   uint         data_count=WHOLE_ARRAY     // O número de valores a partir da buffer de leitura, todo o buffer por defeito
   );

Existem também versões para trabalhar com matrizes e vetores.

Lê o buffer OpenCL em um array e retorna true se for bem-sucedido.

uint  CLBufferRead(
   int           buffer,                    // Um manipulador para o buffer OpenCL
   uint          buffer_offset,             // O deslocamento no buffer OpenCL em bytes
   const matrxi& mat,                       // Um array para obter o valor desde o buffer
   ulong         rows=-1,                   // A quantidade de linhas no array
   ulong         cols=-1                    // A quantidade de colunas no array
   );

Lê o buffer OpenCL no vetor e retorna true se bem-sucedido.

uint  CLBufferRead(
   int           buffer,                    // Um manipulador para o buffer OpenCL
   uint          buffer_offset,             // O deslocamento no buffer OpenCL em bytes
   const vector& vec,                       // O vetor para obter valores a partir do buffer
   ulong         size-1,                    // O tamanho do vetor 
   );

Parâmetros

buffer

[in]   Um manipulador do buffer OpenCL.

data[]

[in]  Um array para receber os valores do buffer OpenCL. Passado por referência.

buffer_offset

[in]  Um deslocamento no buffer OpenCL em bites, a partir da qual se inicia a leitura. Por padrão, a leitura começa com o início do buffer.

data_offset

[in]  O índice do primeiro elemento array para escrever os valores de buffer OpenCL. Por padrão, a escrita dos valores lidos em um array começa a partir do índice zero.

data_count

[in]  O número de valores que devem ser lidos. Todo o buffer OpenCL é lido por padrão.

mat

[out]  O array para a leitura dos dados do buffer pode ser de qualquer um dos três tipos – matrix, matrixf ou matrixc.

vec

[out]  O vetor de leitura dos dados do buffer pode ser de qualquer um dos três tipos – vector, vectorf ou vectorc.

rows=-1

[in]  Se o parâmetro for especificado, o parâmetro cols também deve ser especificado. Se não forem especificadas novas dimensões do array, serão utilizadas as dimensões atuais. Se o valor for -1, o número de linhas não mudará.

cols=-1

[in]  Se não for especificado nenhum parâmetro, o parâmetro rows também deve ser omitido. A regra básica para um array é especificar ambos os parâmetros, ou nenhum deles, caso contrário, ocorrerá um erro. Se os dois parâmetros (rows e cols) forem especificados, a matriz será redimensionada. Se o valor for -1, o número de colunas não mudará.

size=-1

[in]  Se o parâmetro não for especificado ou o valor for -1, o comprimento do vetor não mudará.

Valor do Retorno

O número de elementos de leitura. 0 (zero) é devolvido em caso de erro. Para obter informações sobre o erro, utilize a função GetLastError().

true quando executado com sucesso ao trabalhar com uma matriz ou vetor, no caso de um erro, ele retorna false.

Observação

Para arrays unidimensionais, o número do elemento, em que a escrita de dados num buffer de OpenCL inicia, é calculado tendo em conta os sinalizadores AS_SERIES.

Um array de duas ou mais dimensões é apresentado como unidimensional. Neste caso, data_offset é o número de elementos que devem ser ignorados na apresentação, e não o número de elementos na primeira dimensão.

Exemplode cálculo do número Pi com a fórmula:

pi_calculation_formula

#define  _num_steps        1000000000
#define  _divisor          40000
#define  _step             1.0 / _num_steps
#define  _intrnCnt         _num_steps / _divisor
 
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string D2S(double argint digits) { return DoubleToString(argdigits); }
string I2S(int arg)                { return IntegerToString(arg); }
 
//--- OpenCL programm code
const string clSource=
  "#define _step "+D2S(_step12)+"                   \r\n"
  "#define _intrnCnt "+I2S(_intrnCnt)+"               \r\n"
  "                                                   \r\n"
  "__kernel void Pi( __global double *out )           \r\n"
  "{                                                  \r\n"
  "  int i = get_global_id( 0 );                      \r\n"
  "  double partsum = 0.0;                            \r\n"
  "  double x = 0.0;                                  \r\n"
  "  long from = i * _intrnCnt;                       \r\n"
  "  long to = from + _intrnCnt;                      \r\n"
  "  for( long j = from; j < to; j ++ )               \r\n"
  "  {                                                \r\n"
  "     x = ( j + 0.5 ) * _step;                      \r\n"
  "     partsum += 4.0 / ( 1. + x * x );              \r\n"
  "  }                                                \r\n"
  "  out[ i ] = partsum;                              \r\n"
  "}                                                  \r\n";
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
int OnStart()
 {
  Print("Pi Calculation: step = "+D2S(_step12)+"; _intrnCnt = "+I2S(_intrnCnt));
//--- prepare OpenCL contexts
  int clCtx;
  if((clCtx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL not found");
    return(-1);
   }
  int clPrg = CLProgramCreate(clCtxclSource);
  int clKrn = CLKernelCreate(clPrg"Pi");
  int clMem=CLBufferCreate(clCtx_divisor*sizeof(double), CL_MEM_READ_WRITE);
  CLSetKernelArgMem(clKrn0clMem);
 
  const uint offs[1]  = {0};
  const uint works[1] = {_divisor};
//--- launch OpenCL program
  ulong start=GetMicrosecondCount();
  if(!CLExecute(clKrn1offsworks))
   {
    Print("CLExecute(clKrn, 1, offs, works) failed! Error "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- get results from OpenCL device
  vector buffer(_divisor);
  if(!CLBufferRead(clMem0buffer))
   {
    Print("CLBufferRead(clMem, 0, buffer) failed! Error "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- sum all values to calculate Pi
  double Pi=buffer.Sum()*_step;
 
  double time=(GetMicrosecondCount()-start)/1000.;
  Print("OpenCL: Pi calculated for "+D2S(time2)+" ms");
  Print("Pi = "+DoubleToString(Pi12));
//--- free memory
  CLFreeAll(clMemclKrnclPrgclCtx);
//--- success
  return(0);
 }
  /*
  Pi Calculationstep = 0.000000001000_intrnCnt = 25000
  OpenCLGPU device 'Ellesmereselected
  OpenCLPi calculated for 99.98 ms
  Pi = 3.141592653590
  */ 
//+------------------------------------------------------------------+
//| Auxiliary routine to free memory                                 |
//+------------------------------------------------------------------+
void CLFreeAll(const int clMemconst int clKrnconst int clPrgconst int clCtx)
 {
  CLBufferFree(clMem);
  CLKernelFree(clKrn);
  CLProgramFree(clPrg);
  CLContextFree(clCtx);
 }