前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >使用OpenCV中的universal intrinsics为算法提速 (2)

使用OpenCV中的universal intrinsics为算法提速 (2)

作者头像
OpenCV学堂
发布2020-02-21 13:29:38
2.3K0
发布2020-02-21 13:29:38
举报

前言:因为新型冠状病毒导致疫情,最近几日各种新闻和消息满天飞。疫情之下不易出行、不宜聚会;宜宅在家、宜阅读、宜学习、宜写代码。鉴于此,本系列第2篇提前发布。希望大家过一个充实的春节。


OpenCV 4.x中提供了强大的统一向量指令(universal intrinsics),使用这些指令可以方便地为算法提速。所有的计算密集型任务皆可使用这套指令加速,非计算机视觉算法也可。目前OpenCV的代码加速实现基本上都基于这套指令。

前序文章:使用OpenCV中的universal intrinsics为算法提速 (1)

前序文章介绍了怎么编写C语言代码使用OpenCV中的universal intrinsics来加速。只是写C代码还是不够的,universal intrinsics的使用依赖编译器的选项。

现在我们来看一段测试代码hello.cpp:

(代码较宽,建议横屏阅读)

代码语言:javascript
复制
#include <stdio.h>
#include <opencv2/opencv.hpp>
#include <opencv2/core/simd_intrinsics.hpp>
using namespace cv;

int main(int argc, char ** argv)
{
#ifdef CV_SIMD
    printf("CV_SIMD is : " CVAUX_STR(CV_SIMD) "\n");
    printf("CV_SIMD_WIDTH is : " CVAUX_STR(CV_SIMD_WIDTH) "\n");
    printf("CV_SIMD128 is : " CVAUX_STR(CV_SIMD128) "\n");
    printf("CV_SIMD256 is : " CVAUX_STR(CV_SIMD256) "\n");
    printf("CV_SIMD512 is : " CVAUX_STR(CV_SIMD512) "\n");
#else
    printf("CV_SIMD is NOT defined\n");
#endif

#ifdef CV_SIMD
    printf("sizeof(v_uint8) = %d\n", (int)sizeof(v_uint8));
    printf("sizeof(v_int32) = %d\n", (int)sizeof(v_int32));
    printf("sizeof(v_float32) = %d\n", (int)sizeof(v_float32));
#endif

    return 0;
}

1. X64 CPU+Linux下使用g++编译:

编译命令是:

代码语言:javascript
复制
g++ hello.cpp -o hello -I/usr/local/include/opencv4 -lopencv_core

然后运行

代码语言:javascript
复制
./hello

得到结果如下:

代码语言:javascript
复制
CV_SIMD is : 1
CV_SIMD_WIDTH is : 16
CV_SIMD128 is : 1
CV_SIMD256 is : 0
CV_SIMD512 is : 0
sizeof(v_uint8) = 16
sizeof(v_int32) = 16
sizeof(v_float32) = 16

运行上述程序的计算机的CPU是Intel(R)Core(TM) i7-1065G7 CPU。这个CPU是支持AVX512的,但是上述代码的结果却是只支持128位向量计算(16个字节)。

如果希望支持256位(32个字节)向量计算,编译程序时需要使用选项-mavx2。目前大部分Intel/AMD CPU都支持AVX2。编译命令如下:

代码语言:javascript
复制
g++ hello.cpp -o hello -mavx2 -I/usr/local/include/opencv4 -lopencv_core

然后运行生成的程序,结果如下。可以看出现在向量宽度达到了256位(32个字节)。

代码语言:javascript
复制
CV_SIMD is : 1
CV_SIMD_WIDTH is : 32
CV_SIMD128 is : 1
CV_SIMD256 is : 1
CV_SIMD512 is : 0
sizeof(v_uint8) = 32
sizeof(v_int32) = 32
sizeof(v_float32) = 32

如果希望支持512位(64个字节)向量计算,编译程序时需要使用选项-mavx512f。当然你需要有支持AVX512的CPU;而且版本较低的gcc/g++可能不支持AVX512

代码语言:javascript
复制
g++ hello.cpp -o hello -mavx512ifma -I/usr/local/include/opencv4 -lopencv_core

然后运行生成的程序,结果如下。可以看出现在向量宽度达到了512位(64个字节)。

代码语言:javascript
复制
CV_SIMD is : 1
CV_SIMD_WIDTH is : 64
CV_SIMD128 is : 1
CV_SIMD256 is : 1
CV_SIMD512 is : 1
sizeof(v_uint8) = 64
sizeof(v_int32) = 64
sizeof(v_float32) = 64

特别注意:AVX512有很多不同的扩展,g++支持的有这些:avx512f, avx512pf, avx512eravx512cd, avx512vl avx512bw, avx512dq, avx512ifma, avx512vbmi。大家可以查阅手册确定使用哪一个。例如要使用整数乘法,需要avx512ifma。

2. ARM CPU+Linux下使用g++编译:

本人使用Open AI Lab的EAIDK-310开发板,OpenCV4.2.0,编译命令是:

代码语言:javascript
复制
g++ hello.cpp -o hello -I/usr/local/include/opencv4 -lopencv_core

然后运行

代码语言:javascript
复制
./hello

得到结果如下:

代码语言:javascript
复制
CV_SIMD is : 1
CV_SIMD_WIDTH is : 16
CV_SIMD128 is : 1
CV_SIMD256 is : 0
CV_SIMD512 is : 0
sizeof(v_uint8) = 16
sizeof(v_int32) = 16
sizeof(v_float32) = 16

可以看出g++编译器默认支持了SIMD。

如果你希望更具体的指定ARM CPU上的SIMD指令,g++编译器可以使用选项 -mfpu=neon。其他可选的值还有neon-vpfv4、neon-fp-armv8等。具体由编译器和CPU型号决定。

3. X64 CPU+Windows下使用Visual Studio编译:

打开Visual Studio项目属性页,选择“配置属性”-“代码生成”-“启用增强指令集”,从其中选择你希望使用的指令集。此处不再赘述。

OpenCV中国团队由深圳市人工智能与机器人研究院支持,是一个非营利的开源团队,致力于OpenCV的开发、维护和推广工作。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-01-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档