前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CentOS7下OpenCV2+CUDA9的编译问题解决

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

原创
作者头像
netkiddy
修改2018-12-03 21:57:35
3.2K2
修改2018-12-03 21:57:35
举报

导言

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

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

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 导言
  • 背景
  • 问题
    • nppi命名规范
      • 架构支持
      • 操作
        • OpenCV编译
          • 替换cmake
          • 未知arch时的二次修改
          • 头文件包含
        • 链接问题
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档