加速图像处理的神器: Intel ISPC编译器 (一) ISPC简介

最近刷到这么一篇教程 使用SIMD利器ISPC加速游戏开发

 

简单的上手摸了一下,发现这是个神器,可以帮助我把自己写的单线程的基于C/C++的图像算法编译成SIMD的版本,这样就省得自己手工写SIMD汇编了;同时编译器级的自动优化效率也非常的高,比自己绞尽脑汁的手工调整代码顺序的优化要方便多了 :) 这里强烈的安利一下 :)

 

ISPC相对其他编译器的优势

这里用一段简单的代码对比一下ISPC和MSVC的效率

  • 先看MSVC

首先上一段C代码

代码逻辑就是简单的从vin buffer里依次读count个浮点数,然后算这个浮点数的平方,再写出到vout buffer里

我们可以在https://godbolt.org/ 转换代码对应的MSVC x64编译输出的汇编代码

MSVC,GCC之类的编译器使用的是自动并行化编译的技术,就是由编译器来判断哪些数据可以用SIMD来做并行化处理。用MSVC生成的这段代码可以一眼看到2个问题

  1. 编译器默认是用的SSE指令,SSE寄存器是128bit长,所以一次只能并发4个float乘法。因为代码只会生成一次,所以即使在现在的支持AVX/AVX2的CPU上也只能用到SSE指令,因此不能充分利用一些先进的指令集来提高运算效率
  2. 只有3句C代码的主循环,对应的汇编代码是从line 14到line 33, 单次循环用了太多指令,造成运行效率的低下

 

  • 再看ISPC

先把上面的C代码稍微修改一下,以便用 ISPC的语法,

这个修改工作是非常简单的,ISPC语法里增加了3个keyword来显式的告诉编译器哪里是可以做数据并行化处理的

  1. foreach来代替for,告诉编译器这部分循环里的数据是可以并行化处理的
  2. 变量声明时用uniform标识这个变量不需要做并行化处理,这部分变量默认用EAX,RAX之类的寄存器来存放;用varying来标识此变量是需要并行化处理的(变量声明时默认就是varying),编译器会自动把这个变量用SIMD寄存器来存放

接下来把这段代码放到https://ispc.godbolt.org/看一下ISPC生成的代码

  1. 因为我的电脑支持AVX2, 所以这里生成了AVX指令,一次计算可以做8个浮点乘法。根据ISPC的文档,在编译的时候可以指定生成的指令集类型,也就是说可以同时生成SSE,AVX, AVX2, AVX512等多个指令集的代码,在运行的时候自动根据硬件的类型来调用最符合当前硬件的代码,以此来提高计算效率 。最爽的是还能生成ARM NEON版和Intel GPU的代码,让代码跑在ARM上或者GPU上,赞!!!
  2. 单次循环只用了8条指令,效率比MSVC的单次循环18条指令要高多了 (即使在MSVC编译参数里指定/ARCH:AVX2, 生成的AVX指令数也要多于ISPC, ISPC是基于LLVM的,看来LLVM的编译理念确实领先VC一些)


ISPC的使用方法

接下来看看怎么用这个编译器,

  • 下载安装

编译器的下载非常简单,从官方github上https://github.com/ispc/ispc/releases 下载最新的发行包,支持windows, linux和macOS。 我用的windows版解压缩以后就3个部分

  1. 根目录下的ispc.html和perfguide.html是ISPC的使用手册
  2. bin目录下的ispc.exe就是编译器,不需要安装,也没有依赖库,绿色软件直接使用 (最好把这个bin目录加到系统路径里)
  3. examples目录下面是自带的例子,开源软件通常文档有时候比较难理解,所以读文档的时候需要搭配example例子来阅读理解
  • 编译ISPC代码

编译就非常简单了,把需要编译的ISPC的代码放到一个文件里,直接在命令行下运行

 C:\work\ispc-v1.14.0-windows\bin\ispc.exe C:/work/ispc_test/simple.ispc --target=sse2-i32x4,sse4-i32x8,avx1-i32x8,avx2-i32x8,avx512knl-i32x16,avx512skx-i32x16 --arch=x86-64 -h C:/work/ispc_test/simple_ispc.h -o C:/work/ispc_test/simple_ispc.obj

默认就是带优化参数,所以只需要指定编译需要生成哪些硬件平台就可以, 我这里指定生成sse2/sse4/avx/avx2/avx512的代码

运行后可以看到在C:/work/ispc_test/目录下生成了一些h和obj文件

  • 和现有项目的整合

使用时只需要在现有的项目代码里include生成的simple_ispc.h头文件,把simple()当成一个external的函数来调用;同时在link的时候把ISPC生成的所有obj链接到最终的可执行文件里就可以用了

运行结果, 正确 :)

 

小结

我个人的兴趣就是让代码充分的挖掘出硬件的潜力,SIMD也好,多核也好,尽量的用最便宜最低功耗的硬件方案来达到项目的需求。具体到最近几年玩的推理来说,MKLDNN, OpenVINO可以在推理的时候来发挥硬件的算力。但是就整个推理流程来说,还包括图像的预处理,推理数据的后处理和GUI显示部分,这部分不在OpenVINO的范畴,OpenCV的算法效率也不是那么高,这时候可以利用ISPC来好好搞点事情。在接下来的文章里,我会结合几个实际的图像预处理的代码来看看ISPC给性能带来的变化

  • 6
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值