OpenCL(ccode)

该博客介绍了一个使用C语言调用OpenCL的示例,包括主机端和设备端代码。主要展示了如何创建OpenCL上下文、命令队列、缓冲区,并编译及执行内核函数。示例中包含两个内核函数,分别用于设置缓冲区数据和对数据进行运算。最后,读取并检查结果,确保运算正确。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

例程介绍

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);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值