热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

算法加速的一些方法思路

文章目录0引入1、算法优化2、语言选择3、算法并行3.1指令集加速3.2多核编程3.3CUDA编程加速4、汇编加速5、硬件加速6、引用0引入在实际软件层面应用来说,


文章目录

  • 0 引入
  • 1、算法优化
  • 2、语言选择
  • 3、算法并行
    • 3.1 指令集加速
    • 3.2 多核编程
    • 3.3 CUDA 编程加速
  • 4、汇编加速
  • 5、硬件加速
  • 6、引用




0 引入

在实际软件层面应用来说,一把算法的执行速度还是能够满足需求的,但是在大数据和复杂计算的过程中,由于算法模型的选择和硬件甚至是语言的选择都会影响到算法输出结果的时间,在实时性要求比较高的场合,算法加速往往是绕不开的话题,本文从算法到最后输出的环节,来提供一些可以优化的思想
在这里插入图片描述


  • 算法优化,指降低算法计算复杂度,设计新算法快速求解,比如Hungarian匹配算法。或牺牲一些内存,预计算一些重复计算的过程,减少程序层面的复杂度。
  • 语言更换,指将自己算法迁移到更加底层的算法,越是低级的算法,执行速度越快。常见地,将Matlab、Python等解释性代码移植到C++平台,往往有5-20倍的加速效果。
  • 算法并行,指将自己算法的独立计算部分,分成几块,利用CPU指令集、多核或GPU的特性实现加速。多核并行和CUDA并行最为常见。
  • 汇编加速,将自己的一片代码指定为自己设计的汇编语言。多种C++编译器实际上也是将语言转换为汇编代码,对汇编进行加速在嵌入式中常见。(该方法对平台有需求,并不常见)
  • 硬件加速,利用特殊硬件处理特殊算法,降低CPU架构的复杂度。常见的就是FPGA。
  • cccccccccccccccccccc光学加速,利用参数制作特定的光散射模型,输入目标光源直接得到输出结果。(离谱的加速方式,目前停留在概念)

1、算法优化

算法优化分为两种类型:① 降低算法复杂度;② 减少重复计算过程。




2、语言选择

**越是高级的语言,开发效率越高,执行速度越慢。**

  • 尽量用当前语言的官方库,官方库往往对算法做了足够的加速。
  • 将部分简单函数编译成C++进行调用,比如Python调用C++,或Matlab调用C++。
  • 对并行性较强的,且用了少量STL库的算法使用CUDA加速。
  • 大矩阵运算考虑Eigen,cublas等专用库。
  • 对并行性较强,且用了大量STL库的算法使用多核并行加速。
    将高级代码转换为C++项目,这也是最简单的转换方法了,这样开发出的算法非常容易落地


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指令集需要包含头文件,在QT中需要包含头文件


3.2 多核编程

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


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

3.3 CUDA 编程加速


  • CUDA加速其实是最好的加速手段,CUDA最大的特性就是核心数特别多,一般是几千个,相比于CPU,加速倍数高达20-200倍之间。特别是推出的Jetson NX系列嵌入式卡,核心数在128-512之间,推进了更多算法的落地应用
    CUDA开发主要还是有C语言风格,C++用的很少,切记一点避免在CUDA中动态分配内存,最好通过参数传递内存指针。



4、汇编加速

用汇编加速的方法往往指的是C/C++与汇编混合编程,尽管多种编译器均有优化等级选项,但是越是高级的语言,时间损耗越多。
什么时候使用汇编加速呢? 一般有两种情况需要嵌入汇编代码:


  • ① 升级项目,项目原始版本是汇编代码,现在需要用C++开发,重写汇编代码注定耗时,直接调用汇编是个很好的解决方案。
  • ② 不同的语言对算法一半都有特定的处理方法,比如Matlab之类尽量使用矩阵运算,C++尽量使用指针访问等,如果有个频繁调用的算法,在汇编上有独特的计算方法,那么直接在C++调用这个汇编函数,可以达到加速效果。
    如何嵌入汇编代码呢? 方法很简单,使用关键字__asm来加入一段汇编语言的程序,C++下具体的格式为:__asm{ 指令 [;指令] /* comments */ … 指令}



5、硬件加速

前面介绍了各种通过编程加速的方法,核心是将算法进行并行化处理,总的来说

多核并行&#xff0c;启动并行时需要开多线程&#xff0c;需要少量的时间&#xff08;<10ms)&#xff0c;因此仅适用耗时较长的算法(>100ms)的并行。
CUDA并行&#xff0c;算法不可避免串行过程&#xff0c;因此许多时间在内存和显存之间的拷贝。
CPU指定集&#xff0c;小规模加速&#xff0c;但仅限于各种基本运算操作&#xff08;加减乘除、位运算等&#xff09;。
如今&#xff0c;FPGA是日趋热门的一种加速方法&#xff0c;与软件加速不同&#xff0c;该方法是直接将算法设计在电路上&#xff0c;变成专有模块进行并行。




6、引用

算法加速总的来说就是拿空间换时间&#xff0c;在执行上并行运算&#xff0c;达到加速效果。

1、是科研人就要快&#xff01;加速你的算法&#xff01;
2、C&#43;&#43;中使用SIMD的方法
3、深入代码优化 (二) 使用SIMD优化程序




推荐阅读
author-avatar
大家庭方不_402
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有