CentOS7下OpenCV2+CUDA9的编译问题解决

导言

OpenCV是一个基于(开源)发行的跨平台计算机视觉库。CUDA是由NVIDIA所推出的一种集成技术,透过这个技术,用户可利用NVIDIA的GeForce 8以后的GPU和较新的QuadroGPU进行计算。本文将不涉及OpenCV或者CUDA的更多介绍和使用,主要是提供了对特定版本编译时遇到问题的解决方案。

背景

日前一个项目中的算法部分,一直是依赖于OpenCV2和CUDA8,在项目测试阶段也是完美通过。可在正式上线的时候却在编译OpenCV就一直出错,查到最后才发现生产机器的CUDA版本被人给「偷偷」升级到了CUDA9,也是因此踏上了一条填坑路,记录于下,以被自己所需和他人使用。

如果你是一台全新的环境,当然是按照需要的环境来安装,比如旧版本的OpenCV2 + CUDA8,或者是最新版本的OpenCV4+CUDA10这样的搭配,那么也就不需要再继续阅读下面的内容,因为理论上不会遇到下面的问题。

但是,如果你是在一台已有的环境,且被安装了CUDA9,同时你的代码又依赖于OpenCV2,那么你一定遇到了同样的问题,通过阅读这边文章,你就可以完美的编译并运行你的代码了。

问题

在CUDA9下,我们编译OpenCV2的时候,会遇到了不少报错,主要原因是而相对于CUDA8,在CUDA9中的修改主要是2点:

nppi命名规范

在CUDA9里面,NVIDIA把 libnppi.so换成libnppc.so libnppial.so libnppicc.so libnppicom.so libnppidei.so libnppif.so libnppig.so libnppim.so libnppist.so libnppisu.so libnppitc.so libnpps.so

架构支持

CUDA9.x+里面不支持compute_20 (Fermi)

操作

OpenCV编译

替换cmake

我们在编译OpenCV2时遇到了报错,提示:

nvcc fatal : Unsupported gpu architecture 'compute_20'

这时候,在OpenCV2解压后的{OPENCV_CODE_PATH}/cmake/目录下找到这两个文件:

  • FindCUDA.cmake
  • OpenCVDetectCUDA.cmake

并使用下文中的直接完整替代(可先备份旧文件)

opencv2.4 with CUDA9 patch

上文中,主要是修复了针对问题1和2的修复(如果希望了解具体的替换内容,可参考此链接)。

未知arch时的二次修改

需要注意的是,当我们根据上文进行更改之后,在cmake时需要通过-DCUDA_GENERATION=xxx来指定CUDA的generation信息(如"Fermi" "Kepler" "Maxwell" "Pascal" "Volta")。如果不指定的话,在cmake时OpenCVDetectCUDA.cmake会基于上述所有已知架构完整编译,也是因此,会尝试编译Fermi架构并出现同样的Unsupported gpu architecture错误。

所以,如果我们未知上述的CUDA GENERATION信息的话,需要对OpenCVDetectCUDA.cmake文件再做两处修改,去除关于compute_20 arch的编译信息,因为如上文所说:CUDA9中不再支持2.0框架:

1. 删除Fermi架构的编译分支选项,将下文:

set(__cuda_arch_ptx "")
  if(CUDA_GENERATION STREQUAL "Fermi")
    set(__cuda_arch_bin "2.0")
  elseif(CUDA_GENERATION STREQUAL "Kepler")
    set(__cuda_arch_bin "3.0 3.5 3.7") 
  elseif(CUDA_GENERATION STREQUAL "Maxwell")
    set(__cuda_arch_bin "5.0 5.2")

替换为:

set(__cuda_arch_ptx "")
  if(CUDA_GENERATION STREQUAL "Kepler")
    set(__cuda_arch_bin "3.0 3.5 3.7")
  elseif(CUDA_GENERATION STREQUAL "Maxwell")
    set(__cuda_arch_bin "5.0 5.2")

2. 针对CUDA版本9(大于cmake中的6.5),删除2.x的arch信息,将:

if(${CUDA_VERSION} VERSION_LESS "5.0")
        set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0")
      elseif(${CUDA_VERSION} VERSION_GREATER "6.5")
        set(__cuda_arch_bin "2.0 2.1(2.0) 3.0 3.5")
      else()
        set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0 3.5")
      endif()

替换为:

if(${CUDA_VERSION} VERSION_LESS "5.0")
        set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0")
      elseif(${CUDA_VERSION} VERSION_GREATER "6.5")
        set(__cuda_arch_bin "3.0 3.5")
      else()
        set(__cuda_arch_bin "1.1 1.2 1.3 2.0 2.1(2.0) 3.0 3.5")
      endif()

头文件包含

最后一步,根据 CUDA 9.0 manual所说:

Unsupported Features General CUDA ‣ CUDA library. The built-in functions __float2half_rn() and __half2float() have been removed. Use equivalent functionality in the updated fp16 header file from the CUDA toolkit.

因此我们需要在OpenCV中common.hpp里单独添加该头文件(在{OPENCV_CODE_PATH}目录下通过find命令找到该文件)

#include <cuda_fp16.h>

这时候,我们再次创建编译子目录{OPENCV_CODE_PATH}/mybuild/,并重新进行一次完整的opencv编译操作(在cmake时不必再指定-DCUDA_GENERATION参数了),就可以完美通过了。

链接问题

经过上述的操作,OpenCV的编译环节应该没有任何问题了。然而,在编译我们自己项目代码的时候,依然会遇到链接报错。

/usr/bin/ld: cannot find -lopencv_dep_nppial
/usr/bin/ld: cannot find -lopencv_dep_nppicc
/usr/bin/ld: cannot find -lopencv_dep_nppicom
/usr/bin/ld: cannot find -lopencv_dep_nppidei
/usr/bin/ld: cannot find -lopencv_dep_nppif
/usr/bin/ld: cannot find -lopencv_dep_nppig
/usr/bin/ld: cannot find -lopencv_dep_nppim
/usr/bin/ld: cannot find -lopencv_dep_nppist
/usr/bin/ld: cannot find -lopencv_dep_nppisu
/usr/bin/ld: cannot find -lopencv_dep_nppitc
collect2: error: ld returned 1 exit status

这是因为,如我们上文所说,在CUDA9中更改了nppi的命名规范,这时候,我们需要去CUDA9的lib下找到对应的so文件,并建立正确的软链接。在我的机器上,CUDA9的lib库路径为/usr/local/cuda-9.0/lib64/,遇到同样问题的朋友,可以找到自己机器伤的PATH并替换下面的命令,再执行软连接操作:

 ln -s {CUDA9_LIB_PATH}/libnppial.so /usr/local/lib/libopencv_dep_nppial.so
 ln -s {CUDA9_LIB_PATH}/libnppicc.so /usr/local/lib/libopencv_dep_nppicc.so
 ln -s {CUDA9_LIB_PATH}/libnppicom.so /usr/local/lib/libopencv_dep_nppicom.so
 ln -s {CUDA9_LIB_PATH}/libnppidei.so /usr/local/lib/libopencv_dep_nppidei.so
 ln -s {CUDA9_LIB_PATH}/libnppif.so /usr/local/lib/libopencv_dep_nppif.so
 ln -s {CUDA9_LIB_PATH}/libnppig.so /usr/local/lib/libopencv_dep_nppig.so
 ln -s {CUDA9_LIB_PATH}/libnppim.so /usr/local/lib/libopencv_dep_nppim.so
 ln -s {CUDA9_LIB_PATH}/libnppist.so /usr/local/lib/libopencv_dep_nppist.so
 ln -s {CUDA9_LIB_PATH}/libnppisu.so /usr/local/lib/libopencv_dep_nppisu.so
 ln -s {CUDA9_LIB_PATH}/libnppitc.so /usr/local/lib/libopencv_dep_nppitc.so

通过上述操作,再重新编译我们的代码,这次就全部没有问题了。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

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

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术博文

php 二维码生成类

<?php /** * BarcodeQR - Code QR Barcode Image Generator (PNG) * @package Barco...

4625
来自专栏杨建荣的学习笔记

Data Guard实现故障自动切换(二)(r11笔记第40天)

今天下午我的一个朋友碰到了一个Data Guard的问题,大体是主备网络出现问题,因为环境中配置了自动切换,结果备库就自动切换为了主库,这样就成了“双主”...

40710
来自专栏Timhbw博客

Hexo-完全免费全平台搭建个人博客(2)-域名主题设置

2017-03-1011:01:58 发表评论 913℃热度 Hexo-完全免费全平台搭建个人博客(1)-整体搭建 上一篇文章把 Hexo 博客整体搭建一遍了...

39412
来自专栏腾讯NEXT学位

那些让编码效率起飞(前端)的工具了解一下

? | 导语 想晚上吃鸡?前端编码效率提升工具了解一下? 一、Bash篇(Mac) iTerm2 iTerm 2 is a terminal emulato...

1803
来自专栏刘望舒

Android P 适配指南

Google自 android L (5.0) 以来就持续对安装系统进行 安全 以及 性能上的升级,此次的 android P (9.0)也不例外, 更大程度...

9362
来自专栏xingoo, 一个梦想做发明家的程序员

Elasticsearch推荐插件篇(head,sense,marvel)

安装head head插件可以用来快速查看elasticsearch中的数据概况以及非全量的数据,也支持控件化查询和rest请求,但是体验都不是很好。 一般就用...

3097
来自专栏Jerry的SAP技术分享

不同系统里同一Customizing activity的显示差异分析

比如SAP HANA Live Reporting这个Customizing Activity,在System AG3里不可见,但是在另一个系统QHD里却能使用...

1866
来自专栏程序员笔记

从头开始写一个 Chrome 插件

1795
来自专栏FreeBuf

树莓派随身工具箱:中间人劫持获取控制权

上文讲解了树莓派随身工具箱的环境搭建,这段时间又对其进行了一些优化,主要是从便携美观上面改进。同时,在实际使用中发现了一些问题,并做了小小的改动。

2553
来自专栏杨建荣的学习笔记

假期前的数据库检查脚本之主备关系(r11笔记第46天)

快过年了,很多系统都要进入最后的检查和复验阶段,一方面在节假日前,提前发现问题总比过节的时候发现要好。另一方面如果出现故障的时候能及时进行处理,这个时候我们就需...

28910

扫码关注云+社区

领取腾讯云代金券