CLBufferRead

Lee el búfer OpenCL en un array y devuelve el número de elementos leídos.

uint  CLBufferRead(
   int          buffer,                    // manejador para el búfer OpenCL
   const void&  data[],                    // array de valores
   uint         buffer_offset=0,           // offset en el búfer OpenCL en bytes, por defecto es 0
   uint         data_offset=0,             // offset dentro del array en elementos, por defecto es 0
   uint         data_count=WHOLE_ARRAY     // número de valores del búfer para la lectura, por defecto es el búfer entero
   );

Asimismo, existe una versión para trabajar con matrices y vectores.

Lee el búfer OpenCL en una matriz y retorna true en caso de éxito.

uint  CLBufferRead(
   int           buffer,                    // manejador al búfer OpenCL
   uint          buffer_offset,             // desplazamiento en el búfer OpenCL en bytes
   const matrxi& mat,                       // matriz para obtener los valores  del búfer
   ulong         rows=-1,                   // número de líneas en la matriz
   ulong         cols=-1                    // número de columnas en la matriz
   );

Lee el búfer OpenCL en el vector y retorna true en caso de éxito.

uint  CLBufferRead(
   int           buffer,                    // manejador al búfer OpenCL
   uint          buffer_offset,             // desplazamiento en el búfer OpenCL en bytes
   const vector& vec,                       // vector para obtener los valores de la búfer
   ulong         size-1,                    // longitud del vector 
   );

Parámetros

buffer

[in]  Manejador del búfer OpenCL.

data[]

[in]  Array para recibir valores desde el búfer OpenCL. Se pasa por referencia.

buffer_offset

[in]  Desplazamiento (offset) en el búfer OpenCL en bytes, a partir del cual se empieza la lectura. Por defecto, la lectura se empieza desde el principio del búfer.

data_offset

[in]  Índice del primer elemento del array para la escritura de los valores del búfer OpenCL. Por defecto, los valores leídos se escriben en el array desde el índice cero.

data_count

[in]  Número de valores que hay que leer. Por defecto, se lee el búfer OpenCL entero.

mat

[out]  La matriz para leer los datos del búfer puede ser de cualquiera de los tres tipos – matrix, matrixf o matrixc.

vec

[out]  El vector para leer los datos del búfer puede ser de cualquiera de los tres tipos – vector, vectorf o vectorc.

rows=-1

[in]  Si el parámetro ha sido indicado, también se deberá especificar el parámetro cols. Si no se especifican las nuevas dimensiones de la matriz, se utilizarán las dimensiones actuales. Si el valor es -1, el número de filas no cambiará.

cols=-1

[in]  Si el parámetro no ha sido indicado, el parámetro rows también deberá omitirse. Para las matrices, se aplica la regla siguiente: o bien se indican ambos parámetros, o bien ninguno, de lo contrario se producirá un error. Si se indican ambos parámetros (rows y cols), el tamaño de la matriz será modificado.  Si el valor es igual a -1, el número de columnas no cambiará.

size=-1

[in]  Si el parámetro no ha sido indicado o el valor es -1, la longitud del vector no cambiará.

Valor devuelto

Número de valores leídos. En caso del error, devuelve 0. Para obtener la información sobre el error, utilice la función GetLastError().

true en caso de ejecución exitosa al trabajar con una matriz o vector; en caso de error, se retornará false.

Nota

Para los arrays unidimensionales, el número del elemento en el que se empieza la escritura de datos desde el búfer OpenCL, se calcula teniendo en cuenta la bandera AS_SERIES.

Un array con dos o más dimensiones se representa como unidimensional. En este caso data_offset es el número de elementos que hay que saltar en la representación, y no el número de elementos en la primera dimensión.

Ejemplo de cálculo del número Pi según la 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);
 }