设为首页 加入收藏

TOP

OpenCL之简单的向量加法实现(一)
2015-11-21 01:03:16 来源: 作者: 【 】 浏览:4
Tags:OpenCL 简单 向量 加法 实现

向量加法 程序流程 创建平台 选择设备 创建上下文 创建命令队列 创建程序对象 编译程序 开辟内存 创建Kernel对象 设置Kernel参数 运行Kernel 拷贝结果回主机 释放资源 完整代码 效果截图 Hello World 代码如下

向量加法

程序流程

OpenCL向量加法流程

创建平台

//创建平台对象
status = clGetPlatformIDs( 1, &platform, NULL );
注意:上式是选择默认的第一个平台。如果我们系统中安装不止一个opencl平台,如何选择自己需要的平台? 比如我现在安装了intel和NVIDIA平台。那么我们就需要进行一个选择判断。第一次调用是获取平台的数量,numPlatforms里面存的就是平台的数量。第二个是获取可用的平台。另外,我也没有增加错误检测之类的代码,但是我增加了一个 status 的变量,通常如果函数执行正确,返回的值是 0。

    /*Step1: Getting platforms and choose an available one.*/
    cl_uint numPlatforms;   //the NO. of platforms
    cl_platform_id platform = NULL; //the chosen platform
    cl_int  status = clGetPlatformIDs(0, NULL, &numPlatforms);
    if (status != CL_SUCCESS)
    {
        cout << "Error: Getting platforms!" << endl;
        return FAILURE;
    }

    /*For clarity, choose the first available platform. */
    if(numPlatforms > 0)
    {
        cl_platform_id* platforms = (cl_platform_id* )malloc(numPlatforms* sizeof(cl_platform_id));
        status = clGetPlatformIDs(numPlatforms, platforms, NULL);
        platform = platforms[0];
        free(platforms);
    }

选择设备

询问设备名称,并选择一个。

/*Step 2:Query the platform and choose the first GPU device if has one.Otherwise use the CPU as device.*/
    cl_uint             numDevices = 0;
    cl_device_id        *devices;
    status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, 0, NULL, &numDevices);    
    if (numDevices == 0)    //no GPU available.
    {
        cout << "No GPU device available." << endl;
        cout << "Choose CPU as default device." << endl;
        status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, 0, NULL, &numDevices);    
        devices = (cl_device_id*)malloc(numDevices * sizeof(cl_device_id));
        status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_CPU, numDevices, devices, NULL);
    }
    else
    {
        devices = (cl_device_id*)malloc(numDevices * sizeof(cl_device_id));
        status = clGetDeviceIDs(platform, CL_DEVICE_TYPE_GPU, numDevices, devices, NULL);
    }

创建上下文

下面我们来看下 OpenCL 中 Context 的概念。通常,Context 是指管理 OpenCL 对象和资源的上下文环境。为了管理 OpenCL 程序,下面的一些对象都要和 Context 关联起来:
? 设备(Devices): 执行 Kernel 程序对象。
? 程序对象(Program objects): kernel 程序源代码
? Kernels: 运行在 OpenCL 设备上的函数
? 内存对象(Memory objects): 设备上存放数据
? 命令队列(Command queues): 设备的交互机制
? 内存命令(Memory commands)(用于在主机内存和设备内存之间拷贝数据)
? Kernel 执行(Kernel execution)
? 同步(Synchronization)
注意:创建一个 Context 的时候,我们必须把一个或多个设备和它关联起来。对于其它的 OpenCL 资源,它们创建时候,也要和 Context 关联起来,一般创建这些资源的 OpenCL 函数的输入参数中,都会有 context。

/*Step 3: Create context.*/
cl_context context = clCreateContext(NULL,1, devices,NULL,NULL,NULL);

创建命令队列

接下来,我们要看下命令队列。在 OpenCL 中,命令队列就是主机的请求,在设备上执行的一种机制。
在 Kernel 执行前,我们一般要进行一些内存拷贝的工作,比如把主机内存中的数据传输到设备内存中。
另外要注意的几点就是:对于不同的设备,它们都有自己的独立的命令队列;命令队列中的命令 (kernel 函数)可能是同步的,也可能是异步的,它们的执行顺序可以是有序的,也可以是乱序的。
命令队列在 device 和 context 之间建立了一个连接。
命令队列 properties 指定一下内容:
? 是否乱序执行(在 AMD GPU 中,好像现在还不支持乱序执行)
? 是否启动 profiling。 Profiling 通过事件机制来得到 kernel 执行时间等有用的信息,但它本身也会有一些开销。

/*Step 4: Creating command queue associate with the context.*/
cl_command_queue commandQueue = clCreateCommandQueue(context, devices[0], 0, NULL);

创建程序对象

clCreateProgramWithSource()这个函数通过源代码 (strings),创建一个程序对象,其中 counts 指定源代码串的数量,lengths 指定源代码串的长度(为 NULL 结束的串时,可以省略)。当然,我们还必须自己编写一个从文件中读取源代码串的函数。

/*Step 5: Create program object */
const char *filename = "Vadd.cl";
string sourceStr;
status = convertToString(filename, sourceStr);
const char *source = sourceStr.c_str();
size_t sourceSize[] = {strlen(source)};
cl_program program = clCreateProgramWithSource(context, 1, &source, sourceSize, NULL);
//从文件中读取源代码串的函数
/* convert the kernel file into a string */
int convertToString(const char *filename, std::string& s)
{
    size_t size;
    char*  str;
    std::fstream f(filename, (std::fstream::in | std::fstream::binary));

    if(f.is_open())
    {
        size_t fileSize;
        f.seekg(0, std::fstream::end);
        size = fileSize = (size_t)f.tellg();
        f.seekg(0, std::fstream::beg);
        str = new char[size+1];
        if(!str)
        {
            f.close();
            return 0;
        }

        f.read(str, fileSize);
        f.close();
        str[size] = '\0';
        s = str;
        delete[] str;
        return 0;
    }
    cout<<"Error: failed to open file\n:"<
   

编译程序

/*Step 6: Build progr
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇CF# 149 D Coloring Brackets(区.. 下一篇CSU1602: Needle Throwing Game(..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: