全网第一个c++版本的opencl编程详解(gpu编程)

本文主要讲解opencl在windows下,使用cpp编程的基本过程,使用的IDE是Visual Studio 2017。

下面的代码连在一起就可以运行

step1:新建工程,导入头文件

在VS上新建一个工程,然后配置相关的头文件:视图->其它窗口->属性管理器,然后配置一些项,目的是将opencl的头文件导入这个cpp工程里面。(这里不介绍了,有很多现成的文章)

step2:导入头文件

#include <opencv2/opencv.hpp>  //我的核函数是用来处理图片的,如果不是可以去掉
#include <string>
#include <iostream>
#include <fstream>
#include <sstream>
#include <CL/cl2.hpp>  //cpp版本的opencl的头文件
using namespace cv;
using namespace std;
#pragma warning( disable : 4996 )  //去掉告警信息

step3:获取平台和上下文

cl::Platform platforms = cl::Platform::getDefault();
//我们获取的是gpu设备
cl::Context context = cl::Context(CL_DEVICE_TYPE_GPU,NULL);

 step4:获取设备和命令队列

这里的errNum帮助我们判断每一步是否出错,选中CL_SUCCESS,按F12,就可以看到这些错误码的具体定义

cl_int errNum = CL_SUCCESS;
std::vector<cl::Device> devices = context.getInfo<CL_CONTEXT_DEVICES>();
cl::CommandQueue cq = cl::CommandQueue(context, devices[0], CL_QUEUE_PROFILING_ENABLE, &errNum);	
if(errNum != CL_SUCCESS){
    printf("创建命令队列失败,错误码:%d\n, errNum);
}

step5:创建并且编译Program

main.cl是一个文件,放的是所有的核函数

//读取main.cl中核函数的内容
std::ifstream kernelFile("main.cl", std::ios::in);
std::ostringstream oss;
oss << kernelFile.rdbuf();
std::string srcStdStr = oss.str();
const char *srcStr = srcStdStr.c_str();
//创建Program
//这里要注意,传入的是核函数的内容,而不是核函数所在的文件的名字
program = cl::Program(context, srcStr, false, &errNum);
errNum = program.build(devices);  //编译Program

step6:编写核函数

这段代码放在main.cl文件中,我们这里的main.cl中只有一个核函数,当然,可以有多个

__kernel void kernel_func(__global unsigned char * rgbImage, __global * result)
{
    int x = get_global_id(0);
    int y = get_global_id(1);
    int index = x * height + y;
    result[index] = rgbImage[index];  //这里是输出
}

 step7:为核函数设置参数

Mat image = imread("D://b.jpg");  //存放自己图像的路径 
Mat dst;
cvtColor(image, dst, CV_BGR2GRAY);//图片转灰度图
int imgSize = dst.rows * dst.cols;

//输入的参数
cl::Buffer srcImg(context, CL_MEM_USE_HOST_PTR, sizeof(uchar) * 3 * imgSize, dst.data, &errNum);
//输出的参数
cl::Buffer memResult = cl::Buffer(context, CL_MEM_WRITE_ONLY, sizeof(int)*imgSize,NULL,NULL);
//设置参数
errNum = kernel.setArg(0, sizeof(cl_mem), &srcImg);
errNum = kernel.setArg(1, sizeof(cl_mem), &memResult);

step8:执行核函数

size_t globalThreads[2];
globalThreads[0] = dst.cols;
globalThreads[1] = dst.rows;
errNum = cq.enqueueNDRangeKernel(kernel, cl::NDRange(0), cl::NDRange(globalThreads[0], globalThreads[1]), cl::NullRange, NULL, NULL);

step9:获取执行结果

float * result = new float[imgSize];
errNum = cq.enqueueReadBuffer(memResult, true, 0, sizeof(float)*imgSize, result, NULL, NULL);

 

好的,以下是一个简单的示例程序,使用 OpenCV C++ 接口实现了 OpenCL Mali GPU 加速,并与 CPU 进行了比较: ``` C++ #include <iostream> #include <opencv2/opencv.hpp> #include <opencv2/core/ocl.hpp> using namespace cv; int main(int argc, char** argv) { // 读取图像 Mat img = imread("test.jpg", IMREAD_COLOR); if (img.empty()) { std::cout << "Failed to read image." << std::endl; return -1; } // 将图像转换为灰度图像 Mat gray; cvtColor(img, gray, COLOR_BGR2GRAY); // 创建 OpenCL 上下文 cv::ocl::Context context = cv::ocl::Context::getDefault(); if (!context.ptr()) { std::cout << "Failed to create OpenCL context." << std::endl; return -1; } // 创建 OpenCL 设备 cv::ocl::Device device = cv::ocl::Device::getDefault(); if (!device.available()) { std::cout << "Failed to create OpenCL device." << std::endl; return -1; } // 指定使用 OpenCL 加速 cv::ocl::setUseOpenCL(true); // 将计算任务放到 GPU 上执行 cv::UMat dst; cv::Ptr<cv::CLAHE> clahe = cv::createCLAHE(2.0, cv::Size(8, 8)); clahe->apply(gray, dst); // 将结果拷贝回 CPU Mat result = dst.getMat(ACCESS_READ); // 使用 CPU 进行比较 Mat cpu_result; cv::Ptr<cv::CLAHE> cpu_clahe = cv::createCLAHE(2.0, cv::Size(8, 8)); cpu_clahe->apply(gray, cpu_result); // 比较 CPU 和 GPU 的结果 double error = norm(result, cpu_result, NORM_L2); std::cout << "Error: " << error << std::endl; return 0; } ``` 在上面的代码中,首先读入一张图片并将其转换为灰度图像。然后,创建 OpenCL 上下文和设备,并指定使用 OpenCL 加速。接着,将计算任务放到 GPU 上执行,并将结果拷贝回 CPU。最后,使用 CPU 进行比较,并输出比较结果。 注意,在上面的示例代码中,我们使用了 `cv::UMat` 函数来创建一个能够跨平台运行的 `cv::Mat` 对象,并使用 `ACCESS_READ` 参数获取其 CPU 内存中的数据。另外,我们使用 `cv::norm` 函数计算 CPU 和 GPU 的结果之间的差异。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值