例程介绍
C代码方式调用OpenCL。
例程源码
Host端代码
//main.cpp
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
#include <iostream>
#include <fstream>
#include <signal.h>
#include <cassert>
#include <cstdlib>
#include "ocl_util.h"
#ifdef _TI_RTOS
#include "oclwrapper.dsp_h"
#include "../rtos_main.c"
#endif
using namespace cl;
using namespace std;
char data [1 << 20];
#define BYTES_PER_WG (1 << 12)
#define WGS (sizeof(data)/ BYTES_PER_WG)
/******************************************************************************
* main
******************************************************************************/
#ifdef _TI_RTOS
void ocl_main(UArg arg0, UArg arg1)
{
// int argc = (int) arg0;
// char **argv = (char **) arg1;
#else
#define RETURN(x) return x
int main(int argc, char *argv[])
{
#endif
/*-------------------------------------------------------------------------
* Catch ctrl-c so we ensure that we call dtors and the dsp is reset properly
*------------------------------------------------------------------------*/
signal(SIGABRT, exit);
signal(SIGTERM, exit);
/*-------------------------------------------------------------------------
* Begin OpenCL Setup code in try block to handle any errors
*------------------------------------------------------------------------*/
try
{
//模板化
//创建对应某种设备的context
//获取对应device
Context context(CL_DEVICE_TYPE_ACCELERATOR);
std::vector<Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
/*---------------------------------------------------------------------
* This demo will only setup a Q to dsp0
*--------------------------------------------------------------------*/
CommandQueue Q(context, devices[0]); //创建对应一个device的CommandQueue
Buffer buffer (context, CL_MEM_READ_WRITE, sizeof(data)); //创建对应context的可读可写Buffer
#ifndef _TI_RTOS
/*---------------------------------------------------------------------
* Compile the Kernel Source for the devices
*--------------------------------------------------------------------*/
//模板化创建Program
ifstream t("oclwrapper.cl"); //仅修改文件名即可
std::string kSrc((istreambuf_iterator<char>(t)),
istreambuf_iterator<char>());
Program::Sources source(1, make_pair(kSrc.c_str(), kSrc.length()));
Program program = Program(context, source);
/*---------------------------------------------------------------------
* Build the opencl c code and tell it to link with the specified
* object file.
*--------------------------------------------------------------------*/
program.build(devices, "ccode.obj"); //此处表示连同第二参数项(二进制文件)一起编译
#else
Program::Binaries binary(1, make_pair(oclwrapper_dsp_bin,
sizeof(oclwrapper_dsp_bin)));
Program program = Program(context, devices, binary);
program.build(devices);
#endif
/*---------------------------------------------------------------------
* Call the first kernel -> c code function.
* The result of which should be 0xff written to each element of buffer
*--------------------------------------------------------------------*/
Kernel kernel1(program, "oclwrapper1"); //基于program创建kernel,第二参数项为cl函数名
kernel1.setArg(0, buffer); //cl函数第0参数项
kernel1.setArg(1, BYTES_PER_WG); //cl函数第1参数项
Q.enqueueNDRangeKernel(kernel1, NDRange(0), // offset
NDRange(WGS), // global size
NDRange(1)); // WG size
/*---------------------------------------------------------------------
* Call the second kernel -> c code function.
* The result of which should be 0x7f subtracted from each element
* of buffer.
*
* The modifications to the buffer from the last kernel are still
* valid for the invocation of the second kernel. Ie. the data in the
* buffer is persistent.
*--------------------------------------------------------------------*/
Kernel kernel2(program, "oclwrapper2"); //基于program的oclwrapper2函数创建对应kernel
kernel2.setArg(0, buffer);
kernel2.setArg(1, BYTES_PER_WG);
Q.enqueueNDRangeKernel(kernel2, NDRange(0), // offset
NDRange(WGS), // global size
NDRange(1)); // WG size
/*---------------------------------------------------------------------
* Read the buffer back into host memory
*--------------------------------------------------------------------*/
Q.enqueueReadBuffer(buffer, CL_TRUE, 0, sizeof(data), data);
}
/*-------------------------------------------------------------------------
* Let exception handling deal with any OpenCL error cases
*------------------------------------------------------------------------*/
catch (Error& err)
{
cerr << "ERROR: " << err.what() << "(" << err.err() << ", "
<< ocl_decode_error(err.err()) << ")" << endl;
}
/*-------------------------------------------------------------------------
* Check the buffer for all elements == 0x80
*------------------------------------------------------------------------*/
for (cl_uint i = 0; i < sizeof(data); ++i) assert (data[i] == (char)0x80);
cout << "Success!" << endl;
RETURN(0);
}
//ccode.cpp
void ccode1(char *buf, int size)
{
int i;
for (i=0; i < size; ++i) buf[i] = 0xff;
}
void ccode2(char *buf, int size)
{
int i;
for (i=0; i < size; ++i) buf[i] -= 0x7f;
}
OpenCL设备端代码
kernel void oclwrapper1(global char *buf, int size)
{
int wg_id = get_group_id(0);
ccode1(&buf[wg_id * size], size);
}
kernel void oclwrapper2(global char *buf, int size)
{
int wg_id = get_group_id(0);
ccode2(&buf[wg_id * size], size);
}