现在的卷积实现无非是那么几种:直接卷积、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. React Native使用code-push实现热更新

    这里就不记录了,下面的传送门介绍的通俗易懂,很详细,一步一步很容易实现成功. http://www.jianshu.com/p/f8689ccf0007

  2. 如何调试JS查看异常信息

    如果页面上有错误,html页面的控制台会报错,可以查看报错信息,找到对应的行,找到出错的位置.也可以通过editplus运行调试,editplus会以弹框的形式出现提示,哪行的什么位置什么错误,需要记 ...

  3. selenium+python自动化测试-环境搭建

    firefox浏览器打不开的解决办法: 1.确认将geckodriver拷贝到Firefox安装目录 2.将安装目录添加到Windows的path里 3.重启IDE  

  4. CBES = component-based entity system

    比较好的介绍 CBES 的文章 http://www.richardlord.net/blog/what-is-an-entity-framework

  5. 关于java8中的String

    String 对象的不可变性 java8中的String只有2个属性value和hash,相关代码如下: /** The value is used for character storage. */ ...

  6. Windows下的3389端口渗透

    1.Win7.Win2003.XP系统 在CMD命令行开启3389端口:REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" &qu ...

  7. Debezium系列随笔

    0.Debezium简介 1.Run Debezium for Mysql in docker step by step 2.Run Debezium for SQLServer in docker ...

  8. OpenCV.概念(读书笔记)

    ZC:学习OpenCV.pdf 1.多通道矩阵(学习OpenCV.pdf) 1.1.在学习opencv的时候看到多通道矩阵这一概率,恳求大神告诉我一下什么意思_百度知道.html(https://zh ...

  9. Eclipse配置编写HTML/JS/CSS/JSP页面的自动提示

    我们平时用eclipse开发jsp页面时智能提示效果不太理想,今天用了两个小时发现了eclipse也可以像Visual Studio 2008那样完全智能提示HTML/JS/CSS代码,使用eclip ...

  10. 石子合并/能量项链【区间dp】

    题目链接:http://www.51mxd.cn/problem.php-pid=737.htm 题目大意:给出n个石子堆以及这n个石子堆中石子数目,每次操作合并两个相邻的石子堆,代价为两个石子堆数目 ...