算法加速在实际软件层面应用来说 大数据和复杂计算的过程中
算法优化,指降低算法计算复杂度,设计新算法快速求解,比如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
本文主要介绍算法并行进行加速
**并行思想从小到大可以总结为:**指令集开发->多核并行->CUDA**并行,**
指令集加速,一般是针对CPU架构进行的底层优化,常见于OpenCV和Tensorflow的CPU版本。之所以OpenCV是个经典的开源图像框架,很大原因是因为其在多个平台上执行效率很高,其中底层的优化,比如指令集优化,起到了关键作用。
数据并行的两种实现在计算机体系中,数据并行有两种实现路径:
利用CPU-Z软件可以查看电脑的CPU信息,查看电脑支持哪些指令集。
现代编译器有三种方式来支持 SIMD:
(1)编译器能够在没有用户干预的情况下生成 SIMD 代码,称之为自动矢量化。
(2)用户可以插入 Intrinsics 函数实现 SIMD。
(3)用户可以使用矢量 C++ 类 (仅限ICC编译器) 来实现 SIMD。
在C++中使用SIMD指令集需要包含头文件
多核编程可以理解为就是多线程编程,总体上可以分为三个部分:OpenMP并行,opencv并行和多线程并行。在设计相关代码时候,切记变量可以被多个线程访问,但同一时间只能被一个线程修改,如果多个线程想修改同一个变量,可使用原子操作或加锁。 当然,多核编程不止这些,还有tbb,mkl等等。
1、利用x86转为x64提速,可以提高1倍的速度
2、多线程的openmp或Intel TBB提速,将cpu的利用率从20%多提高到100%
3、利用GPU提速,至少可以提高5~10倍的运算速度
访问图像中像素的三种方法:1. 指针访问_雪易的博客-CSDN博客
访问图像中像素的三种方法:2. 迭代器访问_迭代器访问像素_雪易的博客-CSDN博客
访问图像中像素的三种方法:3. 动态地址计算配合at方法_雪易的博客-CSDN博客
算法加速的一些方法思路_疯狂的挖掘机的博客-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<
TBB——使用lambda进行并行加速_tbb加速_windxgz的博客-CSDN博客
C++ 实现soble算子_qt sobel算子c++实现_酷小川的博客-CSDN博客
sobel算子实现原理和c++实现sobel()检测边缘函数_共觞的博客-CSDN博客
tbb::parallel_for(tbb::blocked_range(0, n), [](const tbb::blocked_range& r)
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指令集。
Intel® Intrinsics Guide 用法参考官网
了解这一类用于进行初始化加载数据以及将暂存器的数据保存到内存相关的指令
使用的xmm0到xmm8的暂存器
其使用方法可以归纳为:“接-化-发”
__m128i p1 = _mm_cvtepu8_epi16(_mm_loadu_si128((__m128i*) (smoothImg + ((i - 1) * src.step + j - 1))));
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博客