RK3588使用openCL

这篇具有很好参考价值的文章主要介绍了RK3588使用openCL。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、opecnCL简介

        OpenCL(全称Open Computing Language,开放运算语言)是第一个面向异构系统通用目的并行编程的开放式、免费标准,也是一个统一的编程环境,便于软件开发人员为高性能计算服务器、桌面计算系统、手持设备编写高效轻便的代码,而且广泛适用于多核心处理器(CPU)、图形处理器(GPU)、Cell类型架构以及数字信号处理器(DSP)等其他并行处理器,在游戏、娱乐、科研、医疗等各种领域都有广阔的发展前景。(抄自百度百科)

        简单的理解,openCL是一种规范,也是一门语言,使用它,可以调用其他处理器如GPU、FPAG、CPU等用于运行代码,代码就是openCL语言写的(在c语言的基础上增加一些特性)。本文使用openCL调用GPU运行代码。

二、rk3588搭建openCL环境

     笔者使用的rk3588固件时是RK官网的ubuntu固件,名字为:ROC-RK3588S-PC_Ubuntu20.04-Gnome-r2202_v1.0.4b_221118.7z。使用官方提供的下载工具 RKDevTool_Release_v2.84下载固件到板子里面。

        在终端里面使用find指令,可以看到openCL对应的库文件和头文件。

RK3588使用openCL

RK3588使用openCL

笔者的板子里面有多个OpenCL库,windows下面指定的库名字时OpenCL,但我这里实际用到的OpenCL库名字时-lmali。笔者使用makefile编译程序,在makefile里面添加对应的库路径和库名字(g++可以找到open CL的头文件)。


OPENCL_LDLIBS = -lmali
OPENCL_LDLIBS_PATH = -L/usr/lib/aarch64-linux-gnu

三、使用OpenCL

        OpenCL的环境还是比较容易搭建的。下面用一个简单的demo展示下rk3588上的mali-610 GPU的效果。

        之前做图像处理时,写了灰度世界算法(自动白平衡算法的一种),功能就是把摄像头的图像进行白平衡处理,原理请参考其他的博客。代码写的比较简单,用了openCV的库打开图像,CPU版本代码如下。

/*
	灰度世界法
	dst_img_buffer: 存放处理过的图像缓存区,默认24位BGR格式 
	src_img_buffer: 原始图像缓存区
	img_w:  图像宽
	img_h:  图像高
	无返回值
*/
void GrayWorldMethod(unsigned char* dst_img_buffer, const unsigned char* src_img_buffer, const int img_w, const int img_h)
{

	int src_img_w = img_w;
	int src_img_h = img_h;
	const unsigned long img_size = src_img_w * src_img_h;  //图像像素尺寸大小   
	const unsigned long img_size_byte = (src_img_w * src_img_h) * 3;  //图像占用多少字节,
	unsigned long long m_R = 0, m_G = 0, m_B = 0;  // RGB分量的平均值
	float R, G, B;
	unsigned char* src_rgb[3]; // 存放RGB分量
	
	src_rgb[0] = (unsigned char*)malloc(img_size_byte);  //  R
	src_rgb[1] = (unsigned char*)malloc(img_size_byte);  //  G
	src_rgb[2] = (unsigned char*)malloc(img_size_byte);  //  B

	//分离 rgb分量,并储存到src_rgb中
	for (int y = 0; y < src_img_h; ++y) {
		for (int x = 0; x < src_img_w; ++x) {
			src_rgb[0][(src_img_w * y + x)] = src_img_buffer[(src_img_w * y + x) * 3 + 2];
			src_rgb[1][(src_img_w * y + x)] = src_img_buffer[(src_img_w * y + x) * 3 + 1];
			src_rgb[2][(src_img_w * y + x)] = src_img_buffer[(src_img_w * y + x) * 3 + 0];  //
			m_R += src_rgb[0][src_img_w * y + x]; //R
			m_G += src_rgb[1][src_img_w * y + x]; //G
			m_B += src_rgb[2][src_img_w * y + x]; //B
		}
	}

	R = m_R * 1.0 / img_size;
	G = m_G * 1.0 / img_size;
	B = m_B * 1.0 / img_size;

	//计算RGB对应的系数
	float K = (R + G + B) / 3.0f, Kr = K / R, Kg = K / G, Kb = K / B;


	// 将RGB进行变换 并写入图像缓冲中
	int Tr, Tg, Tb = 0;
	for (int y = 0; y < src_img_h; ++y) {
		for (int x = 0; x < src_img_w; ++x) {
			Tr = (src_rgb[0][src_img_w * y + x] * Kr);
			Tg = (src_rgb[1][src_img_w * y + x] * Kg);
			Tb = (src_rgb[2][src_img_w * y + x] * Kb);
			dst_img_buffer[(src_img_w * y + x) * 3 + 2] = Tr > 255 ? 255 : Tr;
			dst_img_buffer[(src_img_w * y + x) * 3 + 1] = Tg > 255 ? 255 : Tg;
			dst_img_buffer[(src_img_w * y + x) * 3 + 0] = Tb > 255 ? 255 : Tb;
		}
	}
	free(src_rgb[0]);
	free(src_rgb[1]);
	free(src_rgb[2]);
}

GPU版本代码如下。参数含义参考CPU版本。

unsigned int m_R = 0, m_G = 0, m_B = 0;

/*
    计算RGB分量平均值
*/
__kernel void MeanRGB(
	__global unsigned char* src_img_buffer,
	const int img_w)
{
	int w = get_global_id(0);
	int h = get_global_id(1);
	
	//对每个RGB分量进行运算

	int r = 0, g = 0, b = 0;
	r = src_img_buffer[(h * img_w + w) * 3 + 2];
	g = src_img_buffer[(h * img_w + w) * 3 + 1];
	b = src_img_buffer[(h * img_w + w) * 3 + 0];

	atomic_add(&m_R, r);  //必须原子访问
	atomic_add(&m_G, g);
	atomic_add(&m_B, b);
}

/*
   对图像进行灰度时间算法处理。 
*/
__kernel void GrayWorldMethod(
	__global unsigned char* dst_img_buffer,
	__global const unsigned char* src_img_buffer,
	const int img_w,
	const int img_h)
{
	float R, G, B;
	unsigned int img_size = img_w * img_h;
	int Tr, Tg, Tb = 0;
	int w = get_global_id(0);
	int h = get_global_id(1);

	R = m_R * 1.0 / img_size;
	G = m_G * 1.0 / img_size;
	B = m_B * 1.0 / img_size;

	
	//计算RGB对应的系数
	double K = (R + G + B) / 3.0, Kr = K / R, Kg = K / G, Kb = K / B;
	// 将RGB进行变换 并写入图像缓冲中

	Tr = (src_img_buffer[(h * img_w + w) * 3 + 2] * Kr);
	Tg = (src_img_buffer[(h * img_w + w) * 3 + 1] * Kg);
	Tb = (src_img_buffer[(h * img_w + w) * 3 + 0] * Kb);
	dst_img_buffer[(h * img_w + w) * 3 + 2] = Tr > 255 ? 255 : Tr;
	dst_img_buffer[(h * img_w + w) * 3 + 1] = Tg > 255 ? 255 : Tg;
	dst_img_buffer[(h * img_w + w) * 3 + 0] = Tb > 255 ? 255 : Tb;
	
}

OpenCL参考代码。

size_t global[2];
cl_event prof_event;
global[0] = (size_t)src_img_w;  //工作项设置成图像大小
global[1] = (size_t)src_img_h;

status = clEnqueueNDRangeKernel(cmd_queue, MeanRGB_kernel, 2, NULL, global, NULL, 0, NULL, &prof_event);  //执行GPU代码
if (status)
	cout << "执行内核时错误" << endl;
clFinish(cmd_queue);
status = clEnqueueNDRangeKernel(cmd_queue, GrayWorldMethod_kernel, 2, NULL, global, NULL, 0, NULL, &prof_event);  //执行GPU代码
if (status)
	cout << "执行内核时错误" << endl;
clFinish(cmd_queue);

status = clEnqueueReadBuffer(cmd_queue, memObjects[0], CL_TRUE, 0, img_size_byte, dst_img_buffer, 0, NULL, NULL);//数据拷回 host 内存
if (status)
	perror("读回数据的时候发生错误\n");

这里创建了两个内核函数执行代码。传输数据到显存,执行程序。结果如图

RK3588使用openCL

图像的分辨率1024*768,cpu执行时间时10.6ms,gpu用了1.59ms。执行时间是取十次运行的平均值,速度还是有非常大的提升的。图像处理结果。

RK3588使用openCL

原始图像     

       

RK3588使用openCL

               灰度世界算法处理之后文章来源地址https://www.toymoban.com/news/detail-471470.html

到了这里,关于RK3588使用openCL的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 性能优化-OpenCL 介绍

    「发表于知乎专栏《移动端算法优化》」 本文首先对 GPU 进行了概述,然后着重地对移动端的 GPU 进行了分析,随后我们又详细地介绍了 OpenCL 的背景知识和 OpenCL 的四大编程模型。希望能帮助大家更好地进行移动端高性能代码的开发。 🎬个人简介:一个全栈工程师的升级之

    2024年01月23日
    浏览(26)
  • 【OpenCL基础 · 一】因源

    随着人工智能的发展以及大部分场景中实时性的要求,人们对于计算机算力要求逐渐增加。为了提高计算速度,计算平台从单核发展为多核,从标量数据发展为向量化运算,进而发展到当下流行的 异构并行计算 。 异构,是指计算硬件平台由不同架构的处理器组成 ,如CPU+G

    2024年02月10日
    浏览(61)
  • OpenCL任务调度基础介绍

    当前,科学计算需求急剧增加,基于CPU-GPU异构系统的异构计算在科学计算领域得到了广泛应用,OpenCL由于其跨平台特性在异构计算领域渐为流行,其调度困难的问题也随之暴露,传统的OpenCL任务调度需要在编码阶段确定调度方案,这种人工调度难度高、适应性差、效率低下、

    2024年02月05日
    浏览(64)
  • Windows10+OpenCL环境配置

    一.查看自己电脑的显卡配置支不支持OpenCL 方法1:我的电脑用的是intel的显卡,具体查看方式:桌面右键 → 英特尔显卡设置 → 选项与支持打开英特尔® 显卡控制中心。如果找不到,尝试方法2 方法 2:Windows 开始菜单 在 Windows 开始菜单中 键入 英特尔显卡。找到 英特尔® 显卡

    2024年02月13日
    浏览(26)
  • 性能优化-OpenCL kernel 开发

    「发表于知乎专栏《移动端算法优化》」 本文主要介绍OpenCL的 Kernel,包括代码的实例以及使用注意的详解。 🎬个人简介:一个全栈工程师的升级之路! 📋个人专栏:高性能(HPC)开发基础教程 🎀CSDN主页 发狂的小花 🌄人生秘诀:学习的本质就是极致重复! 目录 一、概述

    2024年01月23日
    浏览(73)
  • GraphicsMagick 的 OpenCL 开发记录(二十)

    2022-04-11 Mon 从 ImageMagick 中拷贝过来的 open_utf8() , fopen_utf8() , stat_utf8() 及 remove_utf8() 函数直接用非 _utf8 的函数代替。 ImageMagick 在 windows 下使用的是宽字符,所以有那样的处理。 且可能遇到 linux 和 windows 的文件名合法性问题, utf8 的处理是必不可少的,但目前不需要 。 之

    2024年01月24日
    浏览(26)
  • OpenCL编程指南-6.2程序对象

    要创建程序对象,可以传入OpenCL C源代码文本,或者利用程序二进制码来创建。由OpenCL C源代码创建程序对象是开发人员创建程序对象的一般做法。OpenCL C程序的源代码放在一个外部文件中(例如,就像我们的示例代码中的.cl文件),应用程序将使用clcreateProgramwithsource()函数由

    2024年02月11日
    浏览(26)
  • 性能优化-OpenCL运行时API介绍

    「发表于知乎专栏《移动端算法优化》」 本文首先给出 OpenCL 运行时 API 的整体编程流程图,然后针对每一步介绍使用的运行时 API,讲解 API 参数,并给出编程运行实例。总结运行时 API 使用的注意事项。最后展示基于 OpenCL 的图像转置代码。在 865 平台下,对于 4096x4096 的 8

    2024年01月24日
    浏览(69)
  • 【高性能计算】opencl安装及相关概念

    异构计算是一种利用多种不同类型的计算资源来协同解决计算问题的方法。它的核心思想是将不同特性和能力的计算设备(例如CPU、GPU、FPGA等)组合在一起,以充分发挥它们在不同类型的工作负载和任务中的优势。 传统的计算模型通常依赖于单一类型的处理器,如中央处理

    2024年02月11日
    浏览(44)
  • OpenCL编程指南-10.1C++包装器API

    C++API划分为多个类,分别映射到一个OpenCL C类型,例如,cl::Memory类就映射到OpenCL C中的cl_mem。不过,C++ API会尽可能使用继承提供额外的一层类型抽象;例如,类cl::Buffer派生自基类cl::Memory,表示所有可能的OpenCL内存对象的1维内存子类。类层次体系结构见图12-1。 一般地,C++类

    2024年02月09日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包