CLBufferWrite

Writes into the OpenCL buffer and returns the number of written elements.

uint  CLBufferWrite(
   int          buffer,                    // A handle to the OpenCL buffer
   const void&  data[],                    // An array of values
   uint         buffer_offset=0,           // An offset in the OpenCL buffer in bytes, 0 by default
   uint         data_offset=0,             // An offset in the array in elements, 0 by default
   uint         data_count=WHOLE_ARRAY     // The number of values from the array for writing, the whole array by default
   );

There are also versions for handling matrices and vectors.

Writes the values from the matrix to the buffer and returns true if successful.

uint  CLBufferWrite(
   int           buffer,                    // a handle to the OpenCL buffer
   uint          buffer_offset,             // an offset in the OpenCL buffer in bytes
   matrix<T>     &mat                       // the values matrix for writing to the buffer
   );

Writes the values from the vector to the buffer and returns true if successful.

uint  CLBufferWrite(
   int           buffer,                    // a handle to the OpenCL buffer
   uint          buffer_offset,             // an offset in the OpenCL buffer in bytes
   vector<T>     &vec                       // the values vector for writing to the buffer
   );

Parameters

buffer

[in]  A handle of the OpenCL buffer.

data[]

[in]  An array of values that should be written in the OpenCL buffer. Passed by reference.

buffer_offset

[in]  An offset in the OpenCL buffer in bytes, from which writing begins. By default, writing start with the very beginning of the buffer.

data_offset

[in]  The index of the first array element, starting from which values from the array are written in the OpenCL buffer. By default, values from the very beginning of the array are taken.

data_count

[in]  The number of values that should be written. All the values of the array, by default.

mat

[out]  The matrix for reading data from the buffer can be any of the three types — matrix, matrixf or matrixc.

vec

[out]  The vector for reading data from the buffer can be of any of the three types — vector, vectorf or vectorc.

Return Value

The number of written elements. 0 is returned in case of an error. For information about the error, use the GetLastError() function.

true if a matrix or a vector is handled successfully, otherwise false.

Note

For one-dimensional arrays, the number of the element, with which reading of data for writing into an OpenCL buffer begins, is calculated taking into account the AS_SERIES flags.

An array of two or more dimensions is presented as one-dimensional. In this case, data_offset is the number of elements that should be skipped in the presentation, not the number of elements in the first dimension.

Example of matrix multiplication using the MatMul method and parallel computing in OpenCL

#define M       3000      // the number of rows in the first matrix
#define K       2000      // the number of columns in the first matrix is equal to the number of rows in the second one 
#define N       3000      // the number of columns in the second matrix
 
//+------------------------------------------------------------------+
const string clSrc=
  "#define N     "+IntegerToString(N)+"                              \r\n"
  "#define K     "+IntegerToString(K)+"                              \r\n"
  "                                                                  \r\n"
  "__kernel void matricesMul( __global float *in1,                   \r\n"
  "                           __global float *in2,                   \r\n"
  "                           __global float *out  )                 \r\n"
  "{                                                                 \r\n"
  "  int m = get_global_id( 0 );                                     \r\n"
  "  int n = get_global_id( 1 );                                     \r\n"
  "  float sum = 0.0;                                                \r\n"
  "  for( int k = 0; k < K; k ++ )                                   \r\n"
  "     sum += in1[ m * K + k ] * in2[ k * N + n ];                  \r\n"
  "  out[ m * N + n ] = sum;                                         \r\n"
  "}                                                                 \r\n";
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- initialize the random number generator
  MathSrand((int)TimeCurrent());
//--- fill in the matrices of a given size with random values
  matrixf mat1(MKMatrixRandom) ;    // first matrix
  matrixf mat2(KNMatrixRandom);     // second matrix
 
//--- calculate the product of matrices using naive method
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// the result of multiplying two matrices is set here
  for(int m=0m<Mm++)
    for(int k=0k<Kk++)
      for(int n=0n<Nn++)
        matrix_naive[m][n]+=mat1[m][k]*mat2[k][n];
  uint time_naive=GetTickCount()-start;   
     
//--- calculate the product of matrices via MatMull
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- calculate the product of matrices in OpenCL
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // context handle
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL not found, leaving");
    return;
   }
  int cl_prg;             // program handle 
  int cl_krn;             // kernel handle
  int cl_mem_in1;         // first (input) buffer handle
  int cl_mem_in2;         // second (input) buffer handle
  int cl_mem_out;         // third (output) buffer handle
//--- create the program and the kernel
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- create all three buffers for three matrices
  cl_mem_in1=CLBufferCreate(cl_ctxM*K*sizeof(float), CL_MEM_READ_WRITE);
  cl_mem_in2=CLBufferCreate(cl_ctxK*N*sizeof(float), CL_MEM_READ_WRITE);
//--- third matrix - output
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- set the kernel arguments
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- write matrices to the device buffers
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- OpenCL code execution time start
  start=GetTickCount();
//--- set the parameters of the task working area and execute the OpenCL program
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- calculate the result to the matrix
  if(CLBufferRead(cl_mem_out0matrix_opencl))
    PrintFormat("[%d x %d] matrix read: "matrix_opencl.Rows(), matrix_opencl.Cols());
   else
      Print("CLBufferRead(cl_mem_out, 0, matrix_opencl failed. Error ",GetLastError()); 
  uint time_opencl=GetTickCount()-start;   
  Print("Compare calculation time using each method");
  PrintFormat("Naive product time = %d ms",time_naive);
  PrintFormat("MatMul product time = %d ms",time_matmul);
  PrintFormat("OpenCl product time = %d ms",time_opencl);  
//--- release all OpenCL contexts
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- compare all obtained result matrices with each other
  Print("How many discrepancy errors are there between result matrices?");
  ulong errors=matrix_naive.Compare(matrix_matmul,(float)1e-12);
  Print("matrix_direct.Compare(matrix_matmul,1e-12)=",errors);
  errors=matrix_matmul.Compare(matrix_opencl,float(1e-12));
  Print("matrix_matmul.Compare(matrix_opencl,1e-12)=",errors);
/*
  Result:
   
   [3000 x 3000] matrix read: 
  Compare the time of calculation with each method
   Naive product time = 54750 ms
   MatMul product time = 4578 ms
   OpenCl product time = 922 ms
   How many discrepancy errors are there between result matrices?
   matrix_direct.Compare(matrix_matmul,1e-12)=0
   matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/  
 }
//+------------------------------------------------------------------+
//| Fills the matrix with random values                              |
//+------------------------------------------------------------------+
void MatrixRandom(matrixfm)
 {
  for(ulong r=0r<m.Rows(); r++)
   {
    for(ulong c=0c<m.Cols(); c++)
     {
      m[r][c]=(float)((MathRand()-16383.5)/32767.);
     }
   }
 }
//+------------------------------------------------------------------+
//| Release all OpenCL contexts                                      |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- delete all contexts created by OpenCL in reverse order
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }