OpenCV算法加速的一些学习总结

news2025/1/13 7:35:56

一、概述

算法加速在实际软件层面应用来说 大数据和复杂计算的过程中

算法优化,指降低算法计算复杂度,设计新算法快速求解,比如Hungarian匹配算法。或牺牲一些内存,预计算一些重复计算的过程,减少程序层面的复杂度。

语言更换,指将自己算法迁移到更加底层的算法,越是低级的算法,执行速度越快。常见地,将Matlab、Python等解释性代码移植到C++平台,往往有5-20倍的加速效果。

算法并行,指将自己算法的独立计算部分,分成几块,利用CPU指令集、多核或GPU的特性实现加速。多核并行和CUDA并行最为常见。

汇编加速,将自己的一片代码指定为自己设计的汇编语言。多种C++编译器实际上也是将语言转换为汇编代码,对汇编进行加速在嵌入式中常见。(该方法对平台有需求,并不常见)

硬件加速,利用特殊硬件处理特殊算法,降低CPU架构的复杂度。常见的就是FPGA。
https://blog.csdn.net/ljsant/article/details/12707525https://blog.csdn.net/ljsant/article/details/12707525

本文主要介绍算法并行进行加速

 其中,3、算法并行

**并行思想从小到大可以总结为:**指令集开发->多核并行->CUDA**并行,**

3.1 指令集加速

指令集加速,一般是针对CPU架构进行的底层优化,常见于OpenCV和Tensorflow的CPU版本。之所以OpenCV是个经典的开源图像框架,很大原因是因为其在多个平台上执行效率很高,其中底层的优化,比如指令集优化,起到了关键作用。

数据并行的两种实现在计算机体系中,数据并行有两种实现路径:

  • MIMD(Multiple Instruction Multiple Data,多指令流多数据流)。MIMD的表现形式主要有多发射、多线程、多核心,在当代设计的以处理能力为目标驱动的处理器中,均能看到它们的身影。
  • SIMD(Single Instruction Multiple Data,单指令流多数据流)。随着多媒体、大数据、人工智能等应用的兴起,为处理器赋予SIMD处理能力变得愈发重要,因为这些应用存在大量细粒度、同质、独立的数据操作,而SIMD天生就适合处理这些操作。SIMD本身并不是一种指令集,而是一种处理思想,现在的一些指令集都支持SIMD。(简单来说,计算1000维向量的点积,乘法是独立的,多核心不值得,这时候就可以利用指令集一次性计算4次或8次乘法,同样的,之后的加法也同样可以用指令集计算)CPU指令集的发展(针对Intel的x86指令集系列):
  • MMX指令集 (Multi Media eXtension, 多媒体扩展指令集)。MMX指令集率先在Pentium处理器中使用,MMX指令集支持算数、比较、移位等运算,MMX指令集的向量寄存器是64bit。
  • SSE指令集(Streaming SIMD Extensions,单指令多数据流扩展),所有的SSE系列指令的向量寄存器都是128bit,也就是一次性可以计算4个int。SSE最早出现在1999年,在之后的近10年内,推出了SSE,SSE2,SSE3,SSE4.1,SSE4.2。AVX指令集(Advanced Vector Extensions,高级向量扩展)。AVX指令集是在之前的SSE128位扩展到和256位的单指令多数据流。AVX出现在2008年,之后出了AVX2,2014年,AVX-512将数据bit由256bit扩展到了512bit。AVX是目前比较常用的指令集,256位的类型可以一次计算4个double,有效的提升性能。

利用CPU-Z软件可以查看电脑的CPU信息,查看电脑支持哪些指令集。

现代编译器有三种方式来支持 SIMD:

(1)编译器能够在没有用户干预的情况下生成 SIMD 代码,称之为自动矢量化。

(2)用户可以插入 Intrinsics 函数实现 SIMD。

(3)用户可以使用矢量 C++ 类 (仅限ICC编译器) 来实现 SIMD。

在C++中使用SIMD指令集需要包含头文件<xmmintrin.h>,在QT中需要包含头文件<immintrin.h>

3.2 多核编程

多核编程可以理解为就是多线程编程,总体上可以分为三个部分:OpenMP并行,opencv并行和多线程并行。在设计相关代码时候,切记变量可以被多个线程访问,但同一时间只能被一个线程修改,如果多个线程想修改同一个变量,可使用原子操作或加锁。 当然,多核编程不止这些,还有tbb,mkl等等。

  1. OpenMP 并行。这种并行办法是最简单的一种并行方法,直接在for循环前面添加#pragma omp parallel for即可,程序会自动将for循环分解。值得注意的是,该方法是在for循环前开始创建线程,结束后并销毁,这个过程会产生一些时间消耗,大约在3-5ms之间,做实时性应用开发的时候需要注意这个问题。(如果用到opencv,内部也有并行)
  2. 多线程并行。上述的两种方法是针对一个for循环来解决的,但是整个算法不可能就由一个for循环构成,如果每个for循环都这么做的话,创建线程的开销巨大,因此,多线程并行主要就是解决这类问题的。初始化时候创建好线程,之后主线程串联算法,子线程解决for循环问题,线程可能会使用同步,加锁等手段逐步执行,最终获得输出结果。创建多线程时候,系统本身就会将不同线程分到不同核心上,有自己的调度手段,所以该方法加速效果很明显,就是过于面向过程,不方便后续的改进。

1、利用x86转为x64提速,可以提高1倍的速度

2、多线程的openmp或Intel TBB提速,将cpu的利用率从20%多提高到100%

3、利用GPU提速,至少可以提高5~10倍的运算速度

OpenCV访问像素的三种方法

访问图像中像素的三种方法:1. 指针访问_雪易的博客-CSDN博客

访问图像中像素的三种方法:2. 迭代器访问_迭代器访问像素_雪易的博客-CSDN博客

访问图像中像素的三种方法:3. 动态地址计算配合at方法_雪易的博客-CSDN博客

二、加速方式

1、OpenMP

算法加速的一些方法思路_疯狂的挖掘机的博客-CSDN博客

OpenCV算法加速(1)OpenMP/PPL/TTB基础知识_利白的博客-CSDN博客_opencv加速

VS中启用OpenMP

在项目上右键->属性->配置属性->C/C++->语言->OpenMP支持,选择“是”即可。

提供指向 OpenMP API 中使用的构造的链接。

循环代码

openMP的一点使用经验_weixin_30449453的博客-CSDN博客

#pragma omp parallel for
     for (int i=0;i<10;i++)
         std::cout<<i<<std::endl;

2、TBB

TBB——使用lambda进行并行加速_tbb加速_windxgz的博客-CSDN博客

C++ 实现soble算子_qt sobel算子c++实现_酷小川的博客-CSDN博客

sobel算子实现原理和c++实现sobel()检测边缘函数_共觞的博客-CSDN博客

TBB_lambda表达式

tbb::parallel_for(tbb::blocked_range<size_t>(0, n), [](const tbb::blocked_range<size_t>& r)

指令集 SIMD指令集(MMX、SSE、AVX)和MIPP


Intel® Intrinsics Guide    用法参考官网

SIMD(Single Instruction Multiple Data ),顾名思义,就是单条指令处理多个数据

        SIMD(Single Instruction Multiple Data)指令集,从第一代开始算起,也快有近20年的历史了,从最开始的MMX技术,到SSE,以及后来的SSE2、SSE3、SSE4、AVX以及11年以后的AVX2,逐渐的成熟和丰富,不过目前考虑通用性方面,AVX的辐射范围还是有限,大部分在优化时还是考虑使用128位的SSE指令集。

3、SSE指令级加速

 
Intel® Intrinsics Guide    用法参考官网

了解这一类用于进行初始化加载数据以及将暂存器的数据保存到内存相关的指令

使用的xmm0到xmm8的暂存器

其使用方法可以归纳为:“接-化-发”

__m128i p1 = _mm_cvtepu8_epi16(_mm_loadu_si128((__m128i*) (smoothImg + ((i - 1) * src.step + j - 1))));
  1. 使用SSE专门的LOAD指令从内存加载一个向量到寄存器。
  2. 使用SSE专门的OP指令对两个向量进行某种计算。
  3. 使用SSE专门的STORE指令把计算结果从寄存机写回到内存。

1. load系列,用于加载数据,从内存到暂存器

__m128 _mm_load_ss (float *p)  
__m128 _mm_load_ps (float *p)  
__m128 _mm_load1_ps (float *p)  
__m128 _mm_loadh_pi (__m128 a, __m64 *p)  
__m128 _mm_loadl_pi (__m128 a, __m64 *p)  
__m128 _mm_loadr_ps (float *p)  
__m128 _mm_loadu_ps (float *p)

MIPP

        MIPP 是用 C++11 编写的向量内在函数 (SIMD) 的可移植和开源包装器(MIT 许可)。 它适用于 SSE、AVX、AVX-512 和 ARM NEON(32 位和 64 位)指令。 MIPP 包装器支持简单/双精度浮点数以及有符号整数运算(64 位、32 位、16 位和 8 位)。
 

OpenMP+SSE  TTB+SSE   AVX加速

tbb+openMP 无法结合,因为他们都是多线程的 多耗时25倍


总结

加速时会消耗内存提高速度 , 消耗内存就是空间换时间

        算法分为空间复杂度和时间复杂度,一般在工作中时间要求更高,可以改变算法逻辑,必要情况下,哪怕提高空间复杂度也要降低时间复杂度

        并发算法都是压榨设备的性能,特别是现在的多核处理器。但是如果设备性能不够高,即使很高的并发也实现不了,而且将串行修改成并行或者并发,都是要额外付出时间的,所以leader说没必要用二维度的range,就是因为公司电脑性能带不动二维,强行使用带不来较一维明显的效果,还压榨设备性能,也会造成硬件的加速老化。

        实际项目中往往牺牲内存提升速度通过开辟更大的内存,即扩大空间复杂度。来降低算法实现的时间复杂度 所以同样的效果其实可以有很多实现方式,而且优劣分明。

加速算法主要就是在空间复杂度时间复杂度上下文章。

电脑提速从而减少浪费内存

1、tbb和OpenMP都是多线程的无法结合进行加速,尝试结合后,时间迸发;

2、tbb加速比较实用的还是lambda表达式的形式;

3、OpenMP使用需要配置VS属性:

在项目上右键->属性->配置属性->C/C++->语言->OpenMP支持,选择“是”即可。提供指向 OpenMP API 中使用的构造的链接。

4、SSE支持的数据类型是4个32位(共计128位)浮点数集合,就是C、C++语言中的float[4],并且必须是以16位字节边界对齐的。因此这也给输入和输出带来了不少的麻烦,实际上主要影响SSE发挥性能的就是不停地对数据进行复制以适用应它的数据格式。

5、用AVX指令集必须做好合适的IDE配置。

在C/C++ ->代码生成的启用增强指令集里


参考文献

https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.htmlIntel® Intrinsics Guide

1、利白老师总结的超详细

OpenCV算法加速(1)OpenMP/PPL/TTB基础知识   

OpenCV算法加速(2)使用SIMD指令集(MMX、SSE、AVX)和MIPP实现视觉算法优化/2、

2、下面博客也很nice

【AI PC端算法优化】四,一步步将Sobel边缘检测加速22倍

[边缘检测算法] Sobel算子及其PC端优化提速20几倍

单线程、SSE、AVX运行效率对比——加法运算

3、sobel算子

sobel算子原理与实现_五仁月饼哭了的博客-CSDN博客

OpenCV图像处理专栏十八 | 手动构造Sobel算子完成边缘检测_just_sort的博客-CSDN博客

Sobel算子及C++实现_chuifuhuo6864的博客-CSDN博客

【学习opencv】Sobel算子原理及其实现_opencv sobel实现_zhulinzhulinlin的博客-CSDN博客

4、TBB入门资料

TBB入门_tbb使用教程_阿尔贝斯的博客-CSDN博客

Intel Thread Building Blocks (TBB) 入门篇_Belial_2010的博客-CSDN博客

VS2010+OpenCV2.3.1环境下使用tbb加速示例_配置tbb加速_小卡36的博客-CSDN博客

Intel Threading Building Blocks :基本算法参考及使用__saga的博客-CSDN博客

Intel TBB 开发指南 2 Parallelizing Simple Loops_sunny_98_98的博客-CSDN博客

C++高性能编程笔记(第6讲 intelTBB入门) - 知乎

Lambda表达式从用到底层原理_恒者走天下的博客-CSDN博客

5、OpenMP学习

OpenMP的配置及简单使用_openmp安装_小白的进阶的博客-CSDN博客

OpenMP并行编程_openmp编程_伴君的博客-CSDN博客

6、SSE学习

SSE指令集学习__mm_srai_epi16_林小鱼的猫的博客-CSDN博客

使用SSE指令集来优化程序_sse2指令集优化_百里杨的博客-CSDN博客

一文读懂SIMD指令集 目前最全SSE/AVX介绍_Axurq的博客-CSDN博客

关于simd:如何选择AVX比较谓词变体 | 码农家园

SSE指令集加速运算_nick_wong的博客-CSDN博客

经典图像二值分割的SSE加速实现_HAOJUN_HAN的博客-CSDN博客

SSE图像算法优化系列1-RGB转灰度图_just_sort的博客-CSDN博客

机器学习中的高性能计算(二)SSE优化 - 知乎

在C/C++代码中使用SSE等指令集的指令(5)SSE进行加法运算简单的性能测试_c++ sse_百里杨的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/444200.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

c语言实例练习笔记

本博文参考题目的地址看右边----》C 语言实例 | 菜鸟教程 以下为个人边练习边敲记录&#xff08;解法不一定和官方一样&#xff0c;会自己扩展一些&#xff0c;练习嘛&#xff0c;肯定是学到的都用上&#xff0c;算检验之前的学进去的是不是对的。&#xff09; C 语言实例 - …

【项目管理】ubuntu2204 图片合成视频

ubuntu 22.04 多张图片合成视频&#xff0c;多个视频合成一个大视频 环境&#xff1a; ubuntu 22.04 LTS 工具&#xff1a; ffmpeg ffmpeg 多张图片合成视频 在 ubuntu 下全选目录下的所有文件&#xff0c;右键 rename, 选择 1,2,3,4 即可&#xff1b;当然也可以使用其他命名方…

uni-app 中模拟器真机运行app

之前打包过app&#xff0c;调试方式是用usb连接电脑和手机&#xff0c;过程中也遇到了很多问题&#xff0c;忘记了怎么解决的&#xff0c;今天又遇到了打包app的项目&#xff0c;因为在开发app这方面经验不足&#xff0c;所以踩了很多坑&#xff0c;花了好几个小时才研究好app在…

学系统集成项目管理工程师(中项)系列06a_信息系统安全管理(上)

1. 信息安全 1.1. 保护信息的保密性、完整性、可用性 1.2. 另外也包括其他属性&#xff0c;如&#xff1a;真实性、可核查性、不可抵赖性和可靠性 2. 信息安全属性及目标 2.1. 保密性(Confidentiality&#xff09; 2.1.1. 信息不被泄露给未授权的个人、实体和过程或不被其…

【python】统计代码行数 | 统计当前文件夹里所有代码文件的行数

背景 写了一堆.cs文件 想看看一共写了多少行 代码 import os import chardet# Check if a file has the given extension def has_extension(file, extension):return os.path.splitext(file)[1] extension# Count the number of non-empty lines in a file def count_line…

拍照时脸背光怎么办?拍摄的逆光人像照如何修复才能更好看?

拍摄逆光人像会产生迷人的轮廓光&#xff0c;发丝看起来会很美丽&#xff0c;并可能拍到好看的星芒&#xff0c;但是&#xff01;直接拍摄很可能经常会对不上焦&#xff0c;或者会拍出大黑脸&#xff0c;这时就需要很多技巧啦。 完成一张好的逆光照片需要前期拍摄和后期修图相…

生成式模型与辨别式模型

分类模型可以分为两大类:生成式模型与辨别式模型。本文解释了这两种模型类型之间的区别&#xff0c;并讨论了每种方法的优缺点。 辨别式模型 辨别式模型是一种能够学习输入数据和输出标签之间关系的模型&#xff0c;它通过学习输入数据的特征来预测输出标签。在分类问题中&…

Revit相关问题:符号线,转转问题,生成三维视图

一、Revit符号线如何画粗一些?如何自定义符号线子类别? 1、Revit在族里面符号线的粗细、显示颜色、显示线型为符号线的子类别控制! 你可以通过&#xff0c;管理选项卡新建子类别&#xff0c;然后在画符号线的时候应用该子类别! 新建符号线对象样式 应用子类别 二、Revit三维模…

YOLOv7+单目跟踪

YOLOv7单目跟踪 1. 目标跟踪2. 测距模块2.1 设置测距模块2.2 添加测距 3. 实验效果 相关链接 1. YOLOv5单目测距&#xff08;python&#xff09; 2. YOLOv7单目测距&#xff08;python&#xff09; 3. 具体效果已在Bilibili发布&#xff0c;点击跳转 1. 目标跟踪 用yolov7实现…

Moviepy模块之视频添加图片水印

文章目录 前言视频添加图片水印1.引入库2.加载视频文件3.加载水印图片4.缩放水印图片大小5.设置水印的位置5.1 相对于视频的左上角5.2 相对于视频的左下角5.3 相对于视频的右上角5.4 相对于视频的右下角5.5 相对于视频的左中位置5.6 相对于视频的正中位置5.7 相对于视频的右中位…

【设计模式】23种设计模式之结构型模式

一、适配器设计模式 1、是什么&#xff1f; 1、适配器模式将某个类的接口转换成客户端期望的另一个接口表示&#xff0c;主要的目的是兼容性&#xff0c;让原本因接口不匹配不能一起工作的两个类可以协同工作 2、适配器模式属于结构型模式 3、主要分为三类&#xff1a;类适配…

【机器学习】EM原理和K-mean聚类

一、教程说明 EM算法就是expect maxmise算法&#xff0c;就是“期望最大化”的缩写。本篇首先提出&#xff1a;1 什么是期望&#xff1f; 2 期望最大化是个啥意思&#xff1f;k-mean聚类中如何用EM算法&#xff1f; 所涉及的概念&#xff1a; 期望 期望的加权平均理解 概率…

工业网关开发:IxCahriot测试吞吐量

吞吐量测试可以确定被测试设备或被测试系统在不丢弃包的情况下&#xff0c;设备或系统能够接受并转发的最大有效数据。在测试中以一定的速率发送一定数量的帧&#xff0c;并计算待测设备接收的帧&#xff0c;如果发送的帧与接受的帧数量相等&#xff0c;那么就将发送速率提高并…

ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7

编辑&#xff1a;ll ASEMI代理ADA4940-1ACPZ-R7原装ADI车规级ADA4940-1ACPZ-R7 型号&#xff1a;ADA4940-1ACPZ-R7 品牌&#xff1a;ADI/亚德诺 封装&#xff1a;LFCSP-16 批号&#xff1a;2023 引脚数量&#xff1a;16 安装类型&#xff1a;表面贴装型 ADA4940-1ACPZ-…

ChatGPT 和 Elasticsearch:OpenAI 遇见私有数据

作者&#xff1a;Jeff Vestal 结合 Elasticsearch 的搜索相关性和 OpenAI 的 ChatGPT 的问答功能来查询你的数据。 在此博客中&#xff0c;你将了解如何使用 Elasticsearch 将 ChatGPT 连接到专有数据存储&#xff0c;并为你的数据构建问答功能。 什么是聊天 GPT&#xff1f; …

Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCVSharp实现图像的对数Log变换算法增强(C#)

Baumer工业相机堡盟工业相机如何联合BGAPISDK和OpenCVSharp实现图像的对数Log变换算法增强&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机使用图像算法增加图像的技术背景Baumer工业相机通过BGAPI SDK联合OpenCV使用图像增强算法1.引用合适的类文件2.BGAPI SDK在图像…

ASEMI代理ADI亚德诺ADA4940-1ACPZ-R7车规级芯片

编辑-Z ADA4940-1ACPZ-R7芯片参数&#xff1a; 型号&#xff1a;ADA4940-1ACPZ-R7 −3 dB小信号带宽&#xff1a;260 MHz −3 dB大信号带宽&#xff1a;25 MHz 0.1dB平坦度的带宽&#xff1a;14.5 MHz 斜率&#xff1a;95 V/s 超速恢复时间&#xff1a;86 ns 输入电压噪…

【数据结构】堆的应用(堆排序的实现 + (向上/向下)建堆时间复杂度证明 + TopK问题(笔记总结))

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;数据结构 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&…

Redis高可用之3种集群方案对比

Redis集群方案使用建议&#xff1a; Redis cluster&#xff1a;除非是1000个节点以上的超大规模集群&#xff0c;优先考虑使用Redis clustercodis&#xff1a;旧项目如果仍在使用codis&#xff0c;可继续使用&#xff0c;但也推荐迁移到Redis clustertwemproxy&#xff1a;不建…

什么是数字化?企业为什么要数字化转型?

什么是数字化&#xff1f;企业为什么要数字化转型&#xff1f; 深度长文&#xff0c;4000字&#xff0c;融合了很多国内外专业期刊观点&#xff0c;一文讲清到底什么是企业数字化转型&#xff1f;心急的小伙伴可以先看目录&#xff1a; 关于定义——到底什么是“数字化转型”…