OpenCl入门——实现简单卷积
现在的卷积实现无非是那么几种:直接卷积、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入门——实现简单卷积的更多相关文章
- OpenCL入门:(二:用GPU计算两个数组和)
本文编写一个计算两个数组和的程序,用CPU和GPU分别运算,计算运算时间,并且校验最后的运算结果.文中代码偏多,原理建议阅读下面文章,文中介绍了OpenCL相关名词概念. http://opencl. ...
- 踢爆IT劣书出版黑幕——由清华大学出版社之《C语言入门很简单》想到的(1)
1.前言与作者 首先声明,我是由于非常偶然的机会获得<C语言入门很简单>这本书的,绝对不是买的.买这种书实在丢不起那人. 去年这书刚出版时,在CU论坛举行试读推广,我当时随口说了几句(没说 ...
- [电子书] 《Android编程入门很简单》
<Android编程入门很简单>是一本与众不同的Android学习读物,是一本化繁为简,把抽象问题具体化,把复杂问题简单化的书.本书避免出现云山雾罩.晦涩难懂的讲解,代之以轻松活泼.由浅入 ...
- Redis入门很简单之六【Jedis常见操作】
Redis入门很简单之六[Jedis常见操作] http://www.tuicool.com/articles/vaqABb http://www.cnblogs.com/stephen-liu74/ ...
- 《Mysql 入门很简单》(读后感①)
下载完整版<Mysql 入门很简单>,点击这里~: http://files.cnblogs.com/files/zhengyeye/MySQL%E5%85%A5%E9%97%A8%E5% ...
- Hibernate入门2.简单的项目开发实例
Hibernate入门2.简单的项目开发实例 这一节通过一个简单的项目学习Hibernate项目的配置 代码下载 : 链接: http://pan.baidu.com/s/1zlgjl 密码: p34 ...
- 资深架构师Sum的故事:正则!入门就是这样简单
| 故事背景 职场如战场!Sum带领三个小队友用了两周,成功把代理功能给干出来了.如果说产品经理是最魔鬼的指挥官,那测试就是最魔鬼的教官.这两周,让Sum深深领略了什么是X市的日出. 不过话又说回来, ...
- Redis入门很简单之七【使用Jedis实现客户端Sharding】
Redis入门很简单之七[使用Jedis实现客户端Sharding] 博客分类: NoSQL/Redis/MongoDB redisjedisspringsharding分片 <一>. 背 ...
- Redis入门很简单之五【Jedis和Spring的整合】
Redis入门很简单之五[Jedis和Spring的整合] 博客分类: NoSQL/Redis/MongoDB redisnosql缓存jedisspring 在上一篇文章中,简单介绍了Jedis的 ...
随机推荐
- C++ STL copy copy_backward
#include <iostream>#include <algorithm>#include <vector>#include <functional> ...
- UICollectionview的头视图和尾视图
UITableView有头视图和尾视图,那么UICollectionView有没有头视图和尾视图呢? 答案是有的. 1.新建一个类,必须继承自 UICollectionReusableView. 2. ...
- swift 第五课 定义model类 和 导航栏隐藏返回标题
1. 网络请求返回数据时候,把数据转化为model,但是有时候会返回空的字符串,所以加载了个长度的判断: class Model : NSObject{ var details_url:String? ...
- 怎么理解linux作业(job),与进程(process)的关系
1.相关概念: shell :命令解释器,其实就是一个脚本语言解释器,有很多种(bash,ash,tcsh等),最常用的是bash. job(作业): 是相对shell 来说的,在shell中执行一条 ...
- Centos7系统下以RPM方式如何安装mysql-5.7
检查系统是否装有mariadb rpm -qa | grep mariadb 卸载mariadb 强制卸载mariadb rpm -e --nodeps mariadb-libs-5.5.35-3.e ...
- 【手记】解决Graphics.DrawImage带ImageAttributes在XP报内存不足的问题
异常信息: System.OutOfMemoryException: 内存不足. 在 System.Drawing.Graphics.CheckErrorStatus(Int32 status) 在 ...
- 【FFMPEG】VS2015编译FFMPEG
系统环境:Windows 10 64位 需要安装的软件和工具: Visual Studio 2015 With Update 3 MSYS2 YASM 一.VS2015 安装VS2015时,选择 ...
- C#实现排列、组合
排列组合的概念 排列:从n个不同元素中取出m(m≤n)个元素,按照一定的顺序排成一列,叫做从n个元素中取出m个元素的一个排列(Arrangement). 组合:从m个不同的元素中,任取n(n≤m)个元 ...
- 35.百度云语音识别接口使用及PyAudio语音识别模块安装
百度云语音识别接口使用: 百度云语音识别接口文档:https://cloud.baidu.com/doc/SPEECH/ASR-API.html#JSON.E6.96.B9.E5.BC.8F.E4.B ...
- 模型预测控制 MPC
使用MPC的原因: