前言:因为新型冠状病毒导致疫情,最近几日各种新闻和消息满天飞。疫情之下不易出行、不宜聚会;宜宅在家、宜阅读、宜学习、宜写代码。鉴于此,本系列第2篇提前发布。希望大家过一个充实的春节。
OpenCV 4.x中提供了强大的统一向量指令(universal intrinsics),使用这些指令可以方便地为算法提速。所有的计算密集型任务皆可使用这套指令加速,非计算机视觉算法也可。目前OpenCV的代码加速实现基本上都基于这套指令。
前序文章:使用OpenCV中的universal intrinsics为算法提速 (1)
前序文章介绍了怎么编写C语言代码使用OpenCV中的universal intrinsics来加速。只是写C代码还是不够的,universal intrinsics的使用依赖编译器的选项。
现在我们来看一段测试代码hello.cpp:
(代码较宽,建议横屏阅读)
#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++编译:
编译命令是:
g++ hello.cpp -o hello -I/usr/local/include/opencv4 -lopencv_core
然后运行
./hello
得到结果如下:
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。编译命令如下:
g++ hello.cpp -o hello -mavx2 -I/usr/local/include/opencv4 -lopencv_core
然后运行生成的程序,结果如下。可以看出现在向量宽度达到了256位(32个字节)。
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
g++ hello.cpp -o hello -mavx512ifma -I/usr/local/include/opencv4 -lopencv_core
然后运行生成的程序,结果如下。可以看出现在向量宽度达到了512位(64个字节)。
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,编译命令是:
g++ hello.cpp -o hello -I/usr/local/include/opencv4 -lopencv_core
然后运行
./hello
得到结果如下:
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的开发、维护和推广工作。