CLBufferRead

Читает буфер OpenCL в массив и возвращает количество прочитанных элементов.

uint  CLBufferRead(
   int          buffer,                    // хендл на буфер OpenCL
   const void&  data[],                    // массив значений
   uint         buffer_offset=0,           // смещение в OpenCL буфере в байтах, по умолчанию 0
   uint         data_offset=0,             // смещение в массиве в элементах, по умолчанию 0
   uint         data_count=WHOLE_ARRAY     // количество значений из буфера для чтения, по умолчанию весь буфер
   );

Существуют также версии для работы матрицами и векторами.

Читает буфер OpenCL в матрицу и возвращает true в случае успеха.

uint  CLBufferRead(
   int           buffer,                    // хендл на буфер OpenCL
   uint          buffer_offset,             // смещение в OpenCL буфере в байтах
   const matrix& mat,                       // матрица для получения значений  из буфера
   ulong         rows=-1,                   // количество строк в матрице
   ulong         cols=-1                    // количество столбцов в матрице
   );

Читает буфер OpenCL в вектор и возвращает true в случае успеха.

uint  CLBufferRead(
   int           buffer,                    // хендл на буфер OpenCL
   uint          buffer_offset,             // смещение в OpenCL буфере в байтах
   const vector& vec,                       // вектор для получения значений из буфера
   ulong         size-1,                    // длина вектора 
   );

Параметры

buffer

[in]  Хендл буфера OpenCL.

data[]

[out]  Массив для получения значений из буфера OpenCL. Передается по ссылке.

buffer_offset

[in]  Смещение в OpenCL буфере в байтах, с которого начинается чтение. По умолчанию чтение начинается с начала буфера.

data_offset

[in]  Индекс первого элемента массива для записи значений буфера OpenCL. По умолчанию запись прочитанных значений в массив начинается с нулевого индекса.

data_count

[in]  Количество значений, которые нужно прочитать. По умолчанию читается весь буфер OpenCL.

mat

[out]  Матрица для чтения данных из буфера может быть любого из трех типов — matrix, matrixf или matrixc.

vec

[out]  Вектор для чтения данных из буфера может быть любого из трех типов — vector, vectorf или vectorc.

rows=-1

[in]  Если параметр указан, то должен быть указан и параметр cols. Если новые размеры матрицы не указаны, то будут использоваться текущие размеры. Если значение равно -1, то число строк не изменится.

cols=-1

[in]  Если параметр не указан, то параметр rows также должен быть пропущен. Для матрицы действует правило: либо указаны оба параметра, либо ни одного, в противном случае возникнет ошибка. Если указаны об параметра (rows и cols), то размер матрицы будет изменен.  Если значение равно -1, то число столбцов не изменится.

size=-1

[in]  Если параметр не указан или значение равно -1, то длина вектора не изменится.

Возвращаемое значение

Количество прочитанных элементов при работе с массивом, в случае ошибки возвращается 0. Для получения информации об ошибке используйте функцию GetLastError().

true при успешном выполнении при работе с матрицей или вектором, в случае ошибки возвращается false.

Примечание

Для одномерных массивов номер элемента, в который начинается запись данных из буфера OpenCL, вычисляется с учётом флага AS_SERIES.

Массив с размерностью два и более  представляется как одномерный. В этом случае data_offset – это количество элементов, которое следует пропустить в представлении, а не количество элементов в первой размерности.

Пример вычисления числа Pi по формуле:

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 программы
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));
//--- создадим OpenCL контексты
  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};
//--- запускаем OpenCL программу
  ulong start=GetMicrosecondCount();
  if(!CLExecute(clKrn1offsworks))
   {
    Print("CLExecute(clKrn, 1, offs, works) failed! Error "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- получим результаты вычисления из OpenCL
  vector buffer(_divisor);
  if(!CLBufferRead(clMem0buffer))
   {
    Print("CLBufferRead(clMem, 0, buffer) failed! Error "GetLastError());
    CLFreeAll(clMemclKrnclPrgclCtx);
    return(-1);
   }
//--- просуммируем все значения для вычисления Pi
  double Pi=buffer.Sum()*_step;
 
  double time=(GetMicrosecondCount()-start)/1000.;
  Print("OpenCL: Pi calculated for "+D2S(time2)+" ms");
  Print("Pi = "+DoubleToString(Pi12));
//--- освободим все OpenCL контексты
  CLFreeAll(clMemclKrnclPrgclCtx);
//--- успешно
  return(0);
 }
  /*
  Pi Calculationstep = 0.000000001000_intrnCnt = 25000
  OpenCLGPU device 'Ellesmereselected
  OpenCLPi calculated for 99.98 ms
  Pi = 3.141592653590
  */ 
//+------------------------------------------------------------------+
//| Освободим все OpenCL контексты                                   |
//+------------------------------------------------------------------+
void CLFreeAll(const int clMemconst int clKrnconst int clPrgconst int clCtx)
 {
  CLBufferFree(clMem);
  CLKernelFree(clKrn);
  CLProgramFree(clPrg);
  CLContextFree(clCtx);
 }