Opencv(C++)学习 TBB与OPENMP的加速效果实验与ARM上的实践(二)

2024-02-01 07:28

本文主要是介绍Opencv(C++)学习 TBB与OPENMP的加速效果实验与ARM上的实践(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在上一篇文章中,我们成功验证了Intel Threading Building Blocks (TBB) 与 OpenMP 在多线程并行处理方面的加速潜力。为了更深入地理解这些技术在实际应用场景中的效能提升,接下来我们将目光转向目标开发板环境,进一步探究这两种框架在嵌入式系统上的实际加速效果。
一、OPENMP加速效果测试
在探讨OPENMP对性能提升的影响时,我们首先遇到了一个有趣的插曲。通常情况下,OpenMP作为一项编译器层面的支持特性,只需在编译阶段通过简单的命令行标志即可启用,例如在使用make构建时追加-fopenmp参数,或在CMake项目中配置如set(CMAKE_CXX_FLAGS “-fopenmp”),即可轻松为项目开启并行处理能力。

然而,在针对RV1106平台的交叉编译环境中,我们发现原生的交叉编译工具链并不支持OpenMP功能。通过执行arm-rockchip830-linux-uclibcgnueabihf-gcc -v来查看编译器详细信息时,注意到其构建选项中包含了–disable-libgomp,这意味着该编译器在构建之初就已排除了对OpenMP库的支持。这可能是因为RV1106芯片本身为单核架构,考虑到硬件资源有限,制造商在设计工具链时并未考虑多线程并行处理的需求。
RV1106交叉编译器能力
尽管如此,面对手头仅有的嵌入式开发环境限制,我们并未止步于此。经过深入研究和探索,最终成功实现了对该交叉编译器OpenMP支持的集成。虽然整个过程尚未完全优化与标准化,此处暂且略过具体实现细节,我们将简要概述如何使编译器支持OpenMP以及随后进行的测试效果评估。

交叉编译器不支持的临时解决办法:
1、从源码编译openmp:
官网介绍:https://www.openmp.org/specifications/
下载地址:https://github.com/OpenMP/sources
编译过程比较简单:在源码中将makefile的configure 后面指定当前的编译工具链路径和生产路径。

all: mkdir src/libgomp/build ;          \cd src/libgomp/build &&            \../configure --host=arm-rockchip830-linux-uclibcgnueabihf && \$(MAKE)

2、编译好的libgomp放入工具链
我生成的libgomp 路径在 libgomp-master\src\libgomp\build.libs 下面,将其中的
libgomp.so libgomp.so.1 libgomp.so.1.0.0 以及上一级目录的libgomp.spec 一共四个文件拷贝到工具链的以下两个路径:

/arm-rockchip830-linux-uclibcgnueabihf/arm-rockchip830-linux-uclibcgnueabihf/lib/lib
/arm-rockchip830-linux-uclibcgnueabihf/arm-rockchip830-linux-uclibcgnueabihf/sysroot/lib/

编译测试:
在编译过程中,直接加入-fopenmp指令:

arm-rockchip830-linux-uclibcgnueabihf-g++ OptCvTestWin.cpp -o test -fopenmp

即可生成可执行文件。
此处不用cmake编译,因为写好的cmakelist中配置的-fopenmp不生效。

加速效果:

# ./test cv F1 Time = 79  rslt 3.20518e+10cv F2 Time = 153  rslt 3.20518e+10cv F1 Time = 91  rslt 2.99779e+10cv F2 Time = 166  rslt 2.99779e+10cv F1 Time = 76  rslt 2.93042e+10cv F2 Time = 166  rslt 2.93042e+10cv F1 Time = 75  rslt 3.1813e+10cv F2 Time = 158  rslt 3.1813e+10cv F1 Time = 75  rslt 3.18925e+10cv F2 Time = 177  rslt 3.18925e+10cv F1 Time = 81  rslt 3.07783e+10cv F2 Time = 158  rslt 3.07783e+10cv F1 Time = 90  rslt 3.05833e+10cv F2 Time = 156  rslt 3.05833e+10cv F1 Time = 76  rslt 2.83669e+10cv F2 Time = 158  rslt 2.83669e+10cv F1 Time = 91  rslt 3.42625e+10cv F2 Time = 170  rslt 3.42625e+10cv F1 Time = 75  rslt 3.44049e+10cv F2 Time = 163  rslt 3.44049e+10

对比了多线程方案F1与常规单线程方案F2的执行速度(单位ms)。实验发现,随着OpenMP线程数从2增至10,F1的加速效果逐步提升;但超过10个线程后,加速收益不再明显增加。这表明存在一个最优线程数阈值,在该范围内使用OpenMP能有效提高程序性能。

测试的代码放出来:
整体上跑10遍观察效果,选取其中一部分数据打印看结果是否一致。

#include <fstream>
#include <iostream>
#include <vector>
//#include <opencv2/opencv.hpp>
//#include "libgomp.h"
#include <future>
#include <thread>
//#include <tbb/parallel_for.h>
//#include <tbb/blocked_range.h>
#include <chrono>
//using namespace cv;
using namespace std;typedef std::chrono::system_clock::time_point SYS_TIME;
SYS_TIME getClock()
{return std::chrono::system_clock::now();
}
double getMsTime(SYS_TIME start, SYS_TIME end)
{return  std::chrono::duration_cast<std::chrono::milliseconds>(end-start).count();
}
int main()
{for (int j =0; j <10; j++)
{const int iCnt = 1000000;std::vector<float> data1(iCnt);std::vector<float> data2(iCnt);for (float i = 0; i < iCnt; ++i) {data1[i] = rand(); // 假设填充了随机整数data2[i] = data1[i];}float fv1=0;SYS_TIME start = getClock();
#pragma omp parallel num_threads(4){
#pragma omp forfor(int i = 0; i < iCnt; i++){data1[i]+=i;if(i>iCnt/3&&i<iCnt/3+30)fv1+=data1[i];}}cout << " cv F1 Time = " << getMsTime(start, getClock()) <<"  rslt "<< fv1  << endl;float fv2=0;SYS_TIME start2 = getClock();{for (float i = 0; i < iCnt; i++){data2[i]+=i;if(i>iCnt/3&&i<iCnt/3+30)fv2+=data2[i];}}cout << " cv F2 Time = " << getMsTime(start2, getClock()) <<"  rslt "<< fv2  << endl;
}    return 0;
}

后记:
在本阶段的技术探索中,我们遇到了CMakeLists.txt中设置的OpenMP编译选项未能生效的问题。尽管GPT暂时无法给出具体原因,但当前的重点已转向验证OpenMP的实际加速效果,并发现尽管其在基准测试中表现出显著优势,但在实际业务工程应用时却遭遇了挑战。由于现有工程完全依赖于由CMake构建的Makefile体系,直接修改Makefile以整合OpenMP支持无疑会增加额外的工作量。
在这里插入图片描述
1、一种解决方案是联系RK(瑞芯微)厂家,请求提供一个内建OpenMP支持的交叉编译器版本,或者自行构建这样一个工具链。然而,鉴于目前的知识储备尚不足以完成这一任务,该方案暂时尚未实施
2、另个一个可行的方案是,将预先编译好的libgomp库作为静态或动态链接库与可执行文件进行链接。这种方法虽然理论上可行,但在调用OpenMP接口和管理库依赖方面可能会遇到复杂性问题,需要进一步技术评估。

接下来的步骤,我们将把注意力转向Intel Threading Building Blocks (TBB) 并行编程库,计划对其进行编译和测试验证,以对比分析其对项目性能提升的效果。

这篇关于Opencv(C++)学习 TBB与OPENMP的加速效果实验与ARM上的实践(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/666518

相关文章

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

C++中实现调试日志输出

《C++中实现调试日志输出》在C++编程中,调试日志对于定位问题和优化代码至关重要,本文将介绍几种常用的调试日志输出方法,并教你如何在日志中添加时间戳,希望对大家有所帮助... 目录1. 使用 #ifdef _DEBUG 宏2. 加入时间戳:精确到毫秒3.Windows 和 MFC 中的调试日志方法MFC

Linux中Curl参数详解实践应用

《Linux中Curl参数详解实践应用》在现代网络开发和运维工作中,curl命令是一个不可或缺的工具,它是一个利用URL语法在命令行下工作的文件传输工具,支持多种协议,如HTTP、HTTPS、FTP等... 目录引言一、基础请求参数1. -X 或 --request2. -d 或 --data3. -H 或

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

基于Python实现PDF动画翻页效果的阅读器

《基于Python实现PDF动画翻页效果的阅读器》在这篇博客中,我们将深入分析一个基于wxPython实现的PDF阅读器程序,该程序支持加载PDF文件并显示页面内容,同时支持页面切换动画效果,文中有详... 目录全部代码代码结构初始化 UI 界面加载 PDF 文件显示 PDF 页面页面切换动画运行效果总结主

Docker集成CI/CD的项目实践

《Docker集成CI/CD的项目实践》本文主要介绍了Docker集成CI/CD的项目实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、引言1.1 什么是 CI/CD?1.2 docker 在 CI/CD 中的作用二、Docke

React实现原生APP切换效果

《React实现原生APP切换效果》最近需要使用Hybrid的方式开发一个APP,交互和原生APP相似并且需要IM通信,本文给大家介绍了使用React实现原生APP切换效果,文中通过代码示例讲解的非常... 目录背景需求概览技术栈实现步骤根据 react-router-dom 文档配置好路由添加过渡动画使用

opencv实现像素统计的示例代码

《opencv实现像素统计的示例代码》本文介绍了OpenCV中统计图像像素信息的常用方法和函数,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一... 目录1. 统计像素值的基本信息2. 统计像素值的直方图3. 统计像素值的总和4. 统计非零像素的数量

在 VSCode 中配置 C++ 开发环境的详细教程

《在VSCode中配置C++开发环境的详细教程》本文详细介绍了如何在VisualStudioCode(VSCode)中配置C++开发环境,包括安装必要的工具、配置编译器、设置调试环境等步骤,通... 目录如何在 VSCode 中配置 C++ 开发环境:详细教程1. 什么是 VSCode?2. 安装 VSCo