现在的卷积实现无非是那么几种:直接卷积、im2col+gemm、局部gemm、wingrod、FFT。如果直接卷积的话,其实kernel函数是比较好实现。以下代码参考至《OpenCL Programing Guide》,主要是main函数各种构造比较麻烦,个人感觉,OpenCL为了追求平台的移植性,使用起来实在是太不方便了。(代码仅表示思路,未测试)

Convolution.cl:

//Convolution.cl
__kernel void convolve(const __global uint * const input, __constant uint *const mask, __global uint * const output, const int inputWidth, const int maskWidth)
{
const int x = get_global_id();
const int y = get_global_id(); uint sum =;
for(int r =;r<maskWidth;r++)
{
const int idxIntmp = (y +r) *inputWidth +x ;
for(int c = ; c<maskWidth;c++)
{
sum +=mask[(r*maskWidth) +c] * input[idxIntmp +c];
}
}
outpu[y* get_global_size() +x] = sum;
}

//Convolution.cpp

//Convolution.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <CL/cl.h> //Constants
const unsigned int inputSignalWidth = ;
const unsigned int inputSignalHeight= ; cl_uint inputSignal[inputSignalWidth][inputSignalHeight] =
{
{, , , , , , , },
{, , , , , , , },
{, , , , , , , },
{, , , , , , , },
{, , , , , , , },
{, , , , , , , },
{, , , , , , , },
{, , , , , , , }
};
const unsigned int outputSignalWidth = ;
const unsigned int outputSignalHeight= ; cl_uint ouputSignal[outputSignalWidth][outputSignalHeight];
const unsigned int maskWidth = ;
const unsigned int maskHeight= ; cl_uint mask[maskWidth][maskHeight] =
{
{, , },
{, , },
{, , }
}; inline void checkErr(cl_int err, const char* name)
{
if(err != CL_SUCCESS)
{
std::cerr <<"ERROR: "<< name
<<" (" << err << ")"<<std::endl;
exit(EXIT_FAILURE);
}
} void CL_CALLBACK contextCallback(const char * errInfo, const void * private_info, size_t cb, void * user_data)
{
std::cout << "Error occurred during context user: "<< errInfo << std::endl;
exit(EXIT_FAILURE);
} int main(int argc, char** argv)
{
cl_int errNum;
cl_uint numPlatforms;
cl_uint numDevices;
cl_platform_id * platformIDs;
cl_context context =NULL;
cl_command_queue queue;
cl_program program;
cl_kernel kernel;
cl_mem inputSignalBuffer;
cl_mem outputSignalBuffer;
cl_mem maskBuffer; errNum = clGetPlatformIDs(, NULL, &numPlatforms);
checkErr( (errNum != CL_SUCCESS )? errNum: (numPlatforms <= ? -: CL_SUCCESS),"clGetPlatformIDs"); deviceIDs = NULL;
cl_uint i;
for(i =; i <numPlatforms; i++)
{
errNum = clGetDeviceIDs(platformIDs[i], CL_DEVICE_TYPE_CPU, , NULL, &numDevices);
if(errNum != CL_SUCCESS && errNum !=CL_DEVICE_NOT_FOUND)
{
checkErr(errNum, "clGetDeviceIDs");
}
else if(numDevices > )
{
deviceIDs = (cl_device_id *)alloca(sizeof(cl_device_id) * numDevices);
break;
}
} cl_context_properties contextProperties[] =
{
CL_CONTEXT_PLATFORM, (cl_context_properties)platformIDs[i],
};
context = clCreateContext(contextProperties, numDevices, deviceIDs,&contextCallback, NULL, &errNum);
checkErr(errNum, "clCreateContext"); std::ifstream srcFile("Convolution.cl");
std::string srcProg(std::istreambuf_iterator<char>(srcFile),(std::istreambuf_iterator<char>())); const char * src = srcProg.c_str();
size_t length = srcProg.length(); program = clCreateProgramWithSource(context, , &src, &length, &errNum);
checkErr(errNum, "clCreateProgramWithSource"); errNum = clBuildProgram(program, numDevices, deviceIDs, NULL, NULL, NULL);
checkErr(errNum, "clBuildProgram"); kernel = clCreateKernel(program, "convolve", &errNum);
checkErr(errNum, "clCreateKernel"); inputSignalBuffer = clCreateBuffer(context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, sizeof(cl_uint) * inputSignalHeight * inputSignalWidth,
static_cast<void*> (inputSignal), &errNum);
checkErr(errNum, "clCreateBuffer(inputSignal)"); maskBuffer = clCreateBuffer(context,CL_MEM_READ_ONLY| CL_MEM_COPY_HOST_PTR, sizeof(cl_uint)* maskHeight *maskWidth, static_cast<void*>(mask), &errNum);
checkErr(errNum, "clCreateBuffer(mask)"); outputSignalBuffer= clCreateBuffer(context,CL_MEM_WRITE_ONLY ,sizeof(cl_uint)* outputSignalHeight *outputSignalWidth, NULL, &errNum);
checkErr(errNum, "clCreateBuffer(outputSignal)"); queue = clCreateCommandQueue(context, deviceIDs[], , &errNum);
checkErr(errNum, "clCreateCommandQueue"); errNum = clSetKernelArg(kernel, , sizeof(cl_mem), &inputSignalBuffer);
errNum |=clSetKernelArg(kernel, , sizeof(cl_mem), &maskBuffer);
errNum |=clSetKernelArg(kernel, , sizeof(cl_mem), &outputSignalBuffer);
errNum |=clSetKernelArg(kernel, , sizeof(cl_uint),&inputSignalWidth);
errNum |=clSetKernelArg(kernel, , sizeof(cl_uint),&maskWidth);
checkErr(errNum, "clSetKernelArg"); const size_t globalWorkSize[] = {outputSignalWidth *outputSignalHeight};
const size_t localWorkSize[] = {}; errNum = clEnqueueNDRangeKernel(queue,kernel, , NULL, globalWorkSize, localWorkSize, , NULL, NULL);
checkErr(errNum, "clEnqueueNDRangeKernel"); errNum = clEnqueueReadBuffer(queue, outputSignalBuffer,CL_TRUE, , sizeof(cl_uint)*outputSignalHeight*outputSignalWidth, outputSignal, , NULL, NULL);
checkErr(errNum, "clEnqueueReadBuffer");
return ;
}

OpenCl入门——实现简单卷积的更多相关文章

  1. OpenCL入门:(二:用GPU计算两个数组和)

    本文编写一个计算两个数组和的程序,用CPU和GPU分别运算,计算运算时间,并且校验最后的运算结果.文中代码偏多,原理建议阅读下面文章,文中介绍了OpenCL相关名词概念. http://opencl. ...

  2. 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(1)

    1.前言与作者 首先声明,我是由于非常偶然的机会获得<C语言入门很简单>这本书的,绝对不是买的.买这种书实在丢不起那人. 去年这书刚出版时,在CU论坛举行试读推广,我当时随口说了几句(没说 ...

  3. [电子书] 《Android编程入门很简单》

    <Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...

  4. Redis入门很简单之六【Jedis常见操作】

    Redis入门很简单之六[Jedis常见操作] http://www.tuicool.com/articles/vaqABb http://www.cnblogs.com/stephen-liu74/ ...

  5. 《Mysql 入门很简单》(读后感①)

    下载完整版<Mysql 入门很简单>,点击这里~: http://files.cnblogs.com/files/zhengyeye/MySQL%E5%85%A5%E9%97%A8%E5% ...

  6. Hibernate入门2.简单的项目开发实例

    Hibernate入门2.简单的项目开发实例 这一节通过一个简单的项目学习Hibernate项目的配置 代码下载 : 链接: http://pan.baidu.com/s/1zlgjl 密码: p34 ...

  7. 资深架构师Sum的故事:正则!入门就是这样简单

    | 故事背景 职场如战场!Sum带领三个小队友用了两周,成功把代理功能给干出来了.如果说产品经理是最魔鬼的指挥官,那测试就是最魔鬼的教官.这两周,让Sum深深领略了什么是X市的日出. 不过话又说回来, ...

  8. Redis入门很简单之七【使用Jedis实现客户端Sharding】

    Redis入门很简单之七[使用Jedis实现客户端Sharding] 博客分类: NoSQL/Redis/MongoDB redisjedisspringsharding分片 <一>. 背 ...

  9. Redis入门很简单之五【Jedis和Spring的整合】

    Redis入门很简单之五[Jedis和Spring的整合] 博客分类: NoSQL/Redis/MongoDB redisnosql缓存jedisspring  在上一篇文章中,简单介绍了Jedis的 ...

随机推荐

  1. 微信小程序如何修改本地缓存key中的单个数据

    假如用户注册后,获得用户手机号和userid,realName默认为0,然后进入B页面进行实名认证,认证成功后realName变为1,再更新缓存里的用户信息. A页面用户注册后,存储用户信息: var ...

  2. (IStool)软件打包时当文件存在时不覆盖文件(配置文件)

    需求:程序实际使用过程中有些配置信息是需要用户手动配置的,不同客户使用配置信息也不同,所以软件发布前需要考虑这个问题,覆盖安装时需要忽略这些配置文件 实现:当对应的目录下由此文件的时候不覆盖此文件 [ ...

  3. 19 个让 MySQL 效率提高 3 倍的 SQL 优化技巧

    优化成本: 硬件>系统配置>数据库表结构>SQL及索引 优化效果: 硬件<系统配置<数据库表结构<SQL及索引 本文我们就来谈谈 MySQL 中常用的 SQL 优化 ...

  4. Vuetify Warning: Unable to locate target [data-app]

    今天在大改 nuxt 项目 layout 的时候,将 Vuetify 的 side nav 换成 Element 的折叠式 nav 后,发现了一个 Warning,虽然不影响使用,但是控制台输出一堆, ...

  5. jvm的内存结构和gc的回收

    推荐这篇文章,说的还比较完整,留个记号,以后方便查看 https://blog.csdn.net/m0_38110132/article/details/74542143

  6. 【DSP开发】DSP能用VS2010生成的链接库文件吗?

    [DSP开发]DSP能用VS2010生成的链接库文件吗? 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 说明:可能这个问题让行家看上去就会莞尔一笑,但是很多 ...

  7. ZOJ Problem Set - 1010

    算法:已知多边形各顶点坐标,求多边形面积的公式 http://www.cnblogs.com/FleetingTime/p/3849957.html http://www.mathchina.net/ ...

  8. MongoDB之源生基础概念与语句测试

    此文章,我们拿MySQL和MongoDB做一个简单的理解. MySQL的数据库 => MongoDB数据库 MySQL的表 => MongoDB的Collection MySQL的一行记录 ...

  9. js函数(5)

    函数属性方法和构造函数 length属性 函数体中,arguments.length表示传入函数的实参个数. prototype属性 指向一个对象的引用 call方法和apply方法 看作是某个对象的 ...

  10. [LuoguP2159][SHOI2009]舞会_动态规划_高精度_排列组合

    舞会 题目链接:https://www.luogu.org/problem/P2159 数据范围:略. 题解: 不会.... 看了题解觉得自己好傻逼啊