CLBufferWrite

写入OpenCL缓冲区以及返回写入元素的个数.

uint  CLBufferWrite(
   int          buffer,                    // 处理一个OpenCL缓冲
   const void&  data[],                    // 值的数组
   uint         buffer_offset=0,           // 字节区偏移的OpenCL缓冲,默认为0
   uint         data_offset=0,             // 元素中数组的偏移,默认为0
   uint         data_count=WHOLE_ARRAY     // 从阵列写入的值的数量,默认整个阵列
   );

这里还有处理矩阵和向量的版本。

将矩阵中的值写入缓冲区,如果成功则返回true。

uint  CLBufferWrite(
   int           buffer,                    // OpenCL缓冲区的句柄
   uint          buffer_offset,             // 以字节为单位的OpenCL缓冲区抵消
   matrix<T>     &mat                       // 用于写入缓冲区的值矩阵
   );

将向量中的值写入缓冲区,如果成功则返回true。

uint  CLBufferWrite(
   int           buffer,                    // OpenCL缓冲区的句柄
   uint          buffer_offset,             // 以字节为单位的OpenCL缓冲区抵消
   vector<T>     &vec                       // 用于写入缓冲区的值向量
   );

参数

buffer

[in]  一个OpenCL缓冲处理.

data[]

[in]  一个用于从OpenCL的缓冲区接收的值的数组。通过引用传递.

buffer_offset

[in]  一个在字节区偏移的OpenCL缓冲,从读取开始处。默认情况下,读取开始于正开头的缓冲.

data_offset

[in]  第一个数组元素的索引,开始于写入OpenCL缓冲数组的值. 默认情况下,取数组正开头的值.

data_count

[in]  应被写入值的数量. 默认数组的所有值.

mat

[out]  用于将数据写入缓冲区的矩阵可以是三种类型中的任何一种 ― matrix、matrixf或matrixc.

vec

[out]  用于将数据写入缓冲区的向量可以是三种类型中的任何一种 ― vector、vectorf或vectorc.

返回值

写入元素的数量. 错误情况下返回0. 有关错误信息,使用 GetLastError() 函数.

如果矩阵或向量成功处理,返回true,否则返回false

注意

对于一维数组,考虑到 AS_SERIES 旗帜,元素的数量,从写入读取数据到一个OpenCL缓冲开始处计算.

两个或两个以上的尺寸数组是一维的。在这种情况下, data_offset 是要在演示文稿中跳过的元素个数,而不是在第一维的元素个数.

使用MatMul方法的矩阵乘法和OpenCL中并行计算的示例

#define M       3000      // 第一个矩阵中的行数
#define K       2000      // 第一个矩阵中的列数等于第二个矩阵的行数
#define N       3000      // 第二个矩阵中的列数
 
//+------------------------------------------------------------------+
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";
//+------------------------------------------------------------------+
//| 脚本程序起始函数                                                   |
//+------------------------------------------------------------------+
void OnStart()
 {
//--- 初始化随机数生成器
  MathSrand((int)TimeCurrent());
//--- 用随机值填写给定大小的矩阵
  matrixf mat1(MKMatrixRandom) ;    // 第一个矩阵
  matrixf mat2(KNMatrixRandom);     //第二个矩阵
 
//--- 使用原始方法计算矩阵的乘积
  uint start=GetTickCount();
  matrixf matrix_naive=matrixf::Zeros(MN);// 在这里设置两个矩阵相乘的结果
  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;   
     
//--- 通过MatMull计算矩阵的乘积
  start=GetTickCount();
  matrixf matrix_matmul=mat1.MatMul(mat2);
  uint time_matmul=GetTickCount()-start;     
  
//--- 在OpenCL中计算矩阵的乘积
  matrixf matrix_opencl=matrixf::Zeros(MN);
  int cl_ctx;             // 环境句柄
  if((cl_ctx=CLContextCreate(CL_USE_GPU_ONLY))==INVALID_HANDLE)
   {
    Print("OpenCL not found, leaving");
    return;
   }
  int cl_prg;             // 程序句柄 
  int cl_krn;             // 内核句柄
  int cl_mem_in1;         // 第一个(输入)缓冲区句柄
  int cl_mem_in2;         // 第二个(输入)缓冲区句柄
  int cl_mem_out;         // 第三个(输出)缓冲区句柄
//--- 创建程序和内核
  cl_prg = CLProgramCreate(cl_ctxclSrc);
  cl_krn = CLKernelCreate(cl_prg"matricesMul");
//--- 为三个矩阵创建所有三个缓冲区
  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);
//--- 第三个矩阵 - 输出
  cl_mem_out=CLBufferCreate(cl_ctxM*N*sizeof(float), CL_MEM_READ_WRITE);
//--- 设置内核参数
  CLSetKernelArgMem(cl_krn0cl_mem_in1);
  CLSetKernelArgMem(cl_krn1cl_mem_in2);
  CLSetKernelArgMem(cl_krn2cl_mem_out);
//--- 将矩阵写入设备缓冲区
  CLBufferWrite(cl_mem_in10mat1);
  CLBufferWrite(cl_mem_in20mat2);
  CLBufferWrite(cl_mem_out0matrix_opencl);
//--- OpenCL代码执行时间开始
  start=GetTickCount();
//--- 设置任务工作区参数,并执行OpenCL程序
  uint  offs[2] = {00};
  uint works[2] = {MN};
  start=GetTickCount();  
  bool ex=CLExecute(cl_krn2offsworks);
//--- 计算矩阵结果
  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);  
//--- 释放所有OpenCL环境
  CLFreeAll(cl_ctxcl_prgcl_krncl_mem_in1cl_mem_in2cl_mem_out);
 
//--- 比较所有获得的结果矩阵
  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);
/*
  结果:
   
   [3000 x 3000] matrix read: 
  比较每种方法的计算时间
   Naive product time = 54750 ms
   MatMul product time = 4578 ms
   OpenCl product time = 922 ms
  结果矩阵之间有多少误差?
   matrix_direct.Compare(matrix_matmul,1e-12)=0
   matrix_matmul.Compare(matrix_opencl,1e-12)=0
*/  
 }
//+------------------------------------------------------------------+
//| 用随机值填写矩阵                                                   |
//+------------------------------------------------------------------+
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.);
     }
   }
 }
//+------------------------------------------------------------------+
//| 释放所有OpenCL环境                                                |
//+------------------------------------------------------------------+
void CLFreeAll(int cl_ctxint cl_prgint cl_krn,
               int cl_mem_in1int cl_mem_in2int cl_mem_out)
 {
//--- 以相反顺序删除OpenCL创建的所有环境
  CLBufferFree(cl_mem_in1);
  CLBufferFree(cl_mem_in2);
  CLBufferFree(cl_mem_out);
  CLKernelFree(cl_krn);
  CLProgramFree(cl_prg);
  CLContextFree(cl_ctx);
 }