IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    记一个编译问题的解决过程

    zhy发表于 2015-05-14 15:01:00
    love 0

    问题描述

    最近在学习caffe,先是在服务器(Ubuntu 14.04)上安装测试,BLAS使用的是atlas。Intel的parallel studio太大了(3.9G),来不及下载,暂时就没有使用。后来又在自己的笔记本上安装,这次使用intel MKL库,结果就在一个问题上折腾了好久。

    问题的大致情况是,编译好了libcaffe.so,后续编译其他工具,链接这个so的时候,报undefined reference错误。

    CXX/LD -o .build_release/tools/convert_imageset.bin
    .build_release/lib/libcaffe.so:对‘cblas_ddot’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_daxpy’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_dasum’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_dcopy’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_sdot’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_dscal’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_sgemm’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_dgemm’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_sgemv’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_sscal’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_scopy’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_saxpy’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_dgemv’未定义的引用
    .build_release/lib/libcaffe.so:对‘cblas_sasum’未定义的引用
    

    问题解决过程

    undefined reference算是一个经典错误。如果出现在源码编译的时候,则可能是没有正确include头文件。这里的错误出现在链接阶段,根据出错信息,问题应该是libcaffe.so缺少需要的定义。

    1. 首先找到出错的地方,使用make -n输出具体的编译命令。
    echo CXX/LD -o .build_release/tools/upgrade_net_proto_text.bin
    g++ .build_release/tools/upgrade_net_proto_text.o -o .build_release/tools/upgrade_net_proto_text.bin -pthread -fPIC -DNDEBUG -O2 -DUSE_CUDNN -I/usr/include/python2.7 -I/usr/lib/python2.7/dist-packages/numpy/core/include -I/usr/local/include -I/opt/opencv/include -I.build_release/src -I./src -I./include -I/usr/local/cuda/include -Wall -Wno-sign-compare -lcaffe -L/usr/lib -L/usr/local/lib -L/usr/lib -L/opt/opencv/lib -L/usr/local/cuda/lib64 -L/usr/local/cuda/lib -L.build_release/lib -lcudart -lcublas -lcurand -lglog -lgflags -lprotobuf -lleveldb -lsnappy -llmdb -lboost_system -lhdf5_hl -lhdf5 -lm -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_imgcodecs -lboost_thread -lstdc++ -lcudnn \
    -Wl,-rpath,\$ORIGIN/../lib

    命令有点长,不过细看一下也不难。找到了出错命令,我们就可以直接执行这条语句测试问题所在了。

    1. 另一方面,错误出在cblas_*,所以在caffe目录搜索用到这些函数的hpp/cpp文件
    find . -name *.[hc]pp |xargs grep cblas
    
    vi include/caffe/util/mkl_alternate.hpp
    #ifdef USE_MKL
    
    #include <mkl.h>
    
    #else  // If use MKL, simply include the MKL header
    
    extern "C" {
    #include <cblas.h>
    }

    如果定义了宏USE_MKL,则包含头文件mkl.h。继续在Makefile中搜索 USE_MKL:

    # BLAS configuration (default = ATLAS)
    BLAS ?= atlas
    ifeq ($(BLAS), mkl)
        # MKL
        LIBRARIES += mkl_rt
        COMMON_FLAGS += -DUSE_MKL
        MKLROOT ?= /opt/intel/mkl
        BLAS_INCLUDE ?= $(MKLROOT)/include
        BLAS_LIB ?= $(MKLROOT)/lib $(MKLROOT)/lib/intel64
    else ifeq ($(BLAS), open)

    Makefile写得一点问题没有。查看Intel MKL安装目录/opt/intel,权限没有问题,头文件也在,这里找不到问题。

    1. 再回到出错命令,仔细想想应该是so文件有问题,去除-lcaffe参数,出错信息就变了,基本确定是libcaffe.so有问题。

    没办法,搜索“link error so undefined reference to”,这个页面的问题有点类似。

    1. 使用两个分析so库文件的命令,ldd分析依赖,nm列出symbol。

    我发现编译出的libcaffe.so的依赖里竟然没有找到关键字blas或intel,而symbol里确实有一大串出错函数。学习了下nm输出结果的Undefined symbol的含义,这些symbol应该由其他库来定义,而现在依赖都没有!

    到/opt/intel/mkl/lib/intel64目录下,nm -A *.so | grep cblas_ddot,找到了3个so,那么到底需要哪一个呢?好不容易搜索找到一个页面,列出mkl里各个so文件的用途,我们要用的应该是libmkl_rt.so。(其实应该搜索intel mkl user guide)

    在出错命令相应位置加入-L/opt/intel/mkl/lib/intel64 -lmkl_rt,运行成功!

    1. 可是为什么mkl的相关参数没有在Makefile中正确生成呢?

    不知道怎么调试makefile,只能一步步echo变量内容,最后定位到问题所在:
    编辑配置文件Makefile.config,设置BLAS,vim编辑的时候,dw删除atlas,光标移动到空格位置,按i插入,按空格,输入mkl。mkl后面多了一个空格,导致后续Makefile条件判断出错!这里应该按a插入...

    这鸟说明的意思有点难以理解,还是实操体验一下吧……

    问题总结

    低级错误,虽然又多了一点经验,但太耗时。只希望遇到问题时,能够冷静分析,精确定位到问题,不然绕了好长的路发现是无用功。

    另外,不知道有什么makefile的调试工具,跟踪每个变量的实际内容,我估计实时打印到标准输出应该就很不错了。



沪ICP备19023445号-2号
友情链接