CLProgramCreate

从源代码创建一个OpenCL程序.

int  CLProgramCreate(

   int           context,     // 处理一个OpenCL背景

   const string  source       // 源代码

   );

参数

context

[in]  处理一个OpenCL背景.

source

[in] OpenCL程序源代码字符串.

返回值

如果成功将处理一个OpenCL对象。一旦出错 -返回1 . 有关错误信息,使用 GetLastError() 函数.

注意

目前,以下错误代码正在使用:

  • ERR_OPENCL_INVALID_HANDLE – OpenCL上下文的无效处理程序。
  • ERR_INVALID_PARAMETER – 无效字符串参数。
  • ERR_NOT_ENOUGH_MEMORY – 完成操作内存不足。
  • ERR_OPENCL_PROGRAM_CREATE – OpenCL 内部错误或编译错误。

在一些图形卡中,默认禁止启用双精度 类型数字。 这可能导致编译错误5105。 若要启用支持双精度类型数字,请添加以下指令到您的OpenCL程序:#pragma OPENCL EXTENSION cl_khr_fp64 : enable

示例:

//+------------------------------------------------------------------+

//| OpenCL kernel                                                    |

//+------------------------------------------------------------------+

const string

cl_src=

       //--- 默认一些 GPU 不支持双精度类型

       //--- cl_khr_fp64 指令用于启用处理双精度类型

       "#pragma OPENCL EXTENSION cl_khr_fp64 : enable      \r\n"

       //--- OpenCL 核函数

       "__kernel void Test_GPU(__global double *data,      \r\n"

       "                       const    int N,             \r\n"

       "                       const    int total_arrays)  \r\n"

       "  {                                                \r\n"

       "   uint kernel_index=get_global_id(0);             \r\n"

       "   if (kernel_index>total_arrays) return;          \r\n"

       "   uint local_start_offset=kernel_index*N;         \r\n"

       "   for(int i=0; i<N; i++)                          \r\n"

       "     {                                             \r\n"

       "       data[i+local_start_offset] *= 2.0;          \r\n"

       "     }                                             \r\n"

       "  }                                                \r\n";

//+------------------------------------------------------------------+

//| Test_CPU                                                         |

//+------------------------------------------------------------------+

bool Test_CPU(double &data[],const int N,const int id,const int total_arrays)

  {

//--- 检查数组大小

   if(ArraySize(data)==0) return(false);

//--- 检查数组索引

   if(id>total_arrays) return(false);

//--- 通过索引id计算数组局部偏移

   int local_start_offset=id*N;

//--- 元素乘以2

   for(int i=0; i<N; i++)

     {

      data[i+local_start_offset]*=2.0;

     }

   return true;

  }

//---

#define ARRAY_SIZE   100  // size of the array

#define TOTAL_ARRAYS 5    // total arrays

//--- OpenCL 处理程序

int cl_ctx;  // OpenCL 内容处理

int cl_prg;  // OpenCL 程序处理

int cl_krn;  // OpenCL 核处理

int cl_mem;  // OpenCL 缓冲处理

//---

double DataArray1[]; // 用于CPU计算的数据数组

double DataArray2[]; // 用于GPU计算的数据数组

//+------------------------------------------------------------------+

//| 脚本程序起始函数                                   |

//+------------------------------------------------------------------+

int OnStart()

  {

//--- 初始化OpenCL对象

//--- 创建OpenCL 环境

   if((cl_ctx=CLContextCreate())==INVALID_HANDLE)

     {

      Print("OpenCL not found. Error=",GetLastError());

      return(1);

     }

//--- 创建 OpenCL 程序

   if((cl_prg=CLProgramCreate(cl_ctx,cl_src))==INVALID_HANDLE)

     {

      CLContextFree(cl_ctx);

      Print("OpenCL program create failed. Error=",GetLastError());

      return(1);

     }

//--- 创建OpenCL 内核

   if((cl_krn=CLKernelCreate(cl_prg,"Test_GPU"))==INVALID_HANDLE)

     {

      CLProgramFree(cl_prg);

      CLContextFree(cl_ctx);

      Print("OpenCL kernel create failed. Error=",GetLastError());

      return(1);

     }

//--- 创建 OpenCL 缓冲

   if((cl_mem=CLBufferCreate(cl_ctx,ARRAY_SIZE*TOTAL_ARRAYS*sizeof(double),CL_MEM_READ_WRITE))==INVALID_HANDLE)

     {

      CLKernelFree(cl_krn);

      CLProgramFree(cl_prg);

      CLContextFree(cl_ctx);

      Print("OpenCL buffer create failed. Error=",GetLastError());

      return(1);

     }

//--- 设置OpenCL 内核常量参数

   CLSetKernelArgMem(cl_krn,0,cl_mem);

   CLSetKernelArg(cl_krn,1,ARRAY_SIZE);

   CLSetKernelArg(cl_krn,2,TOTAL_ARRAYS);

//--- 准备数据数组

   ArrayResize(DataArray1,ARRAY_SIZE*TOTAL_ARRAYS);

   ArrayResize(DataArray2,ARRAY_SIZE*TOTAL_ARRAYS);

//--- 用数据填写数组

   for(int j=0; j<TOTAL_ARRAYS; j++)

     {

      //--- 计算 jth 数组局部开始偏移

      uint local_offset=j*ARRAY_SIZE;

      //--- 准备 j 索引数组

      for(int i=0; i<ARRAY_SIZE; i++)

        {

         //--- 用MathCos(i+j)函数填写数组;

         DataArray1[i+local_offset]=MathCos(i+j);

         DataArray2[i+local_offset]=MathCos(i+j);

        }

     };

//--- 测试CPU 计算

   for(int j=0; j<TOTAL_ARRAYS; j++)

     {

      //--- 计算 j 索引数组 

      Test_CPU(DataArray1,ARRAY_SIZE,j,TOTAL_ARRAYS);

     }

//--- 准备 CLExecute 参数

   uint  offset[]={0};

//--- 全局工作大小

   uint  work[]={TOTAL_ARRAYS};

//--- 编写数据到 OpenCL 缓冲

   CLBufferWrite(cl_mem,DataArray2);

//--- 执行OpenCL 内核

   CLExecute(cl_krn,1,offset,work);

//--- 从OpenCL缓冲阅读数据

   CLBufferRead(cl_mem,DataArray2);

//--- 总误差

   double total_error=0;

//--- 比较结果和计算误差

   for(int j=0; j<TOTAL_ARRAYS; j++)

     {

      //--- 计算 jth 数组局部偏移

      uint local_offset=j*ARRAY_SIZE;

      //--- 比较结果

      for(int i=0; i<ARRAY_SIZE; i++)

        {

         double v1=DataArray1[i+local_offset];

         double v2=DataArray2[i+local_offset];

         double delta=MathAbs(v2-v1);

         total_error+=delta;

         //--- 显示初始和最后的数组

         if((j==0) || (j==TOTAL_ARRAYS-1))

            PrintFormat("array %d of %d, element [%d]:  %f, %f, [error]=%f",j+1,TOTAL_ARRAYS,i,v1,v2,delta);

        }

     }

   PrintFormat("Total error: %f",total_error);

//--- 删除OpenCL 对象

//--- 释放 OpenCL 缓冲

   CLBufferFree(cl_mem);

//--- 释放 OpenCL 内核

   CLKernelFree(cl_krn);

//--- 释放 OpenCL 程序

   CLProgramFree(cl_prg);

//--- 释放 OpenCL 环境

   CLContextFree(cl_ctx);

//---

   return(0);

  }