4

我正在尝试按照本教程安装 caffe

基本上我在输入最后一个 make 命令时出现以下错误:

me@dl-01:/home/me/caffe-master$ make runtest

.build_release/tools/caffe

caffe: command line brew

usage: caffe command args

commands:

train           train or finetune a model

test            score a model

device_query    show GPU diagnostic information

time            benchmark model execution time

Flags from tools/caffe.cpp:
 -gpu (Run in GPU mode on given device ID.) type: int32 default: -1
 -iterations (The number of iterations to run.) type: int32 default: 50
 -model (The model definition protocol buffer text file..) type: string
      default: ""
 -snapshot (Optional; the snapshot solver state to resume training.)
 type: string default: ""
 -solver (The solver definition protocol buffer text file.) type: string
 default: ""
 -weights (Optional; the pretrained weights to initialize finetuning. Cannot
      be set simultaneously with snapshot.) type: string default: ""
.build_release/test/test_all.testbin 0 --gtest_shuffle 
ERROR: something wrong with flag 'flagfile' in file '/root/glog-0.3.3/gflags-master/src/gflags.cc'.  One possibility: file '/root/glog-0.3.3/gflags-master/src/gflags.cc' is being linked both statically and dynamically into this executable.
make: *** [runtest] Error 1

我不明白如何解决这个错误。以前有人发现这个错误吗?我该如何解决?

4

3 回答 3

10

无论您是否已经在其他地方解决了这个问题,我都会在这里发布答案,以防其他人遇到同样的问题。

首先,这个问题似乎已经出现,因为我们并不总是正确地阅读内容并且盲目地遵循所有说明,认为它们都适用于我们的案例。提示:他们没有。

在 Caffe 的安装说明(假设是 Ubuntu 说明)中,有一段说明:

一切都打包在 14.04 中。

sudo apt-get install libgflags-dev libgoogle-glog-dev liblmdb-dev protobuf-compiler

一味地忽略了下一个标题,上面写的很清楚:

剩余的依赖,12.04

我们继续安装这些依赖项,根据需要构建和安装,导致不幸的副作用是有 2 个版本的 libgflags,一个是动态的(在/usr/lib[/x86_x64],一个是静态的)/usr/local/lib

解析度

  1. 向自己保证,我们下次会正确阅读说明。

  2. 卸载 libgflags

    sudo apt-get remove -y libgflags
    
  3. 删除make install版本

    sudo rm -f /usr/local/lib/libgflags.a /usr/local/lib/libgflags_nothreads.a
    sudo rm -rf  /usr/local/include/gflags
    
  4. 清洁 Caffe 构建

    cd <path>/<to>/caffe
    make clean
    
  5. 重新安装 libgflags 包

    sudo apt-get install -y libgflags-dev
    
  6. 重建 Caffe

    make all
    make test
    make runtest
    

等瞧。现在所有测试都应该运行了,你已经准备好驾驭深度学习的船了。

于 2015-07-05T10:10:59.927 回答
3

我已经找到了一种分析调试这个问题的方法。就我而言,我正在为较旧的 ABI 进行交叉编译,因此 apt-get 不是一个选项,我正在手动编译所有依赖项。

首先让我们来看看这个问题究竟是什么。在 Google GFlags 库中,标志是通过全局对象声明的。当全局对象的构造函数运行时,它调用 GFlags 库来注册该命令行标志。如果全局构造函数多次运行(由于包含它的库的多个版本被加载到内存中),则 GFlags 注册方法会因错误而终止。

GLog 与此有什么关系?好吧,GLog 使用 GFlags,并且它具有全局声明的标志对象。即使 GFlags 已正确链接,如果 GLog 库被多次加载,您也会收到指向 GLog 中 logging.cc 的错误。

听起来很乱,呵呵。即使 GLog 和 GFlags 在大多数情况下被链接为共享,如果另一个库链接到静态版本或其他版本,kaboom。

幸运的是,如果您愿意深入研究一些棘手的符号分析,我们可以使用 GDB 和其他工具调试此问题。首先,当 Python 解释器尝试导入 caffe 时,您需要在 GDB 上运行它:

gdb --args python -c 'import caffe'

现在,运行程序一次,以便 GDB 可以获取它导入的所有库:

(gdb) r

现在,我们可以在函数 ( FlagRegistry::RegisterFlag()) 中打印错误消息的位置设置断点,然后再次运行它。请注意,此行号来自我的 GFlags 版本(2.2.2),您可能需要查看 GFlags 版本的源代码并获取行号。

(gdb) break gflags.c:728
(gdb) r

希望 GDB 应该在错误的第一个实例上中断(如果没有,请检查 gflags 是否已使用调试符号构建)。查看回溯:

(gdb) bt
#0  google::(anonymous namespace)::FlagRegistry::RegisterFlag (this=0xa33b30, flag=0x1249d20) at dev/gflags-2.2.2/src/gflags.cc:728
#1  0x00007ffff0f3247a in _GLOBAL__sub_I_logging.cc () from prefix/lib/libcaffe2.so
#2  0x00007ffff7de76ca in call_init (l=<optimized out>, argc=argc@entry=3, argv=argv@entry=0x7fffffffdb08, env=env@entry=0x7fffffffdb28) at dl-init.c:72
#3  0x00007ffff7de77db in call_init (env=0x7fffffffdb28, argv=0x7fffffffdb08, argc=3, l=<optimized out>) at dl-init.c:30
#4  _dl_init (main_map=main_map@entry=0xd9c2a0, argc=3, argv=0x7fffffffdb08, env=0x7fffffffdb28) at dl-init.c:120
#5  0x00007ffff7dec8f2 in dl_open_worker (a=a@entry=0x7fffffffcf70) at dl-open.c:575
#6  0x00007ffff7de7574 in _dl_catch_error (objname=objname@entry=0x7fffffffcf60, errstring=errstring@entry=0x7fffffffcf68, mallocedp=mallocedp@entry=0x7fffffffcf5f, 
    operate=operate@entry=0x7ffff7dec4e0 <dl_open_worker>, args=args@entry=0x7fffffffcf70) at dl-error.c:187
#7  0x00007ffff7debdb9 in _dl_open (file=0x9aee70 "prefix/lib/python2.7/site-packages/caffe2/python/caffe2_pybind11_state.so", mode=-2147483646, 
    caller_dlopen=0x51bb39 <_PyImport_GetDynLoadFunc+233>, nsid=-2, argc=<optimized out>, argv=<optimized out>, env=0x7fffffffdb28) at dl-open.c:660
#8  0x00007ffff75ecf09 in dlopen_doit (a=a@entry=0x7fffffffd1a0) at dlopen.c:66
#9  0x00007ffff7de7574 in _dl_catch_error (objname=0xabf9f0, errstring=0xabf9f8, mallocedp=0xabf9e8, operate=0x7ffff75eceb0 <dlopen_doit>, args=0x7fffffffd1a0) at dl-error.c:187
#10 0x00007ffff75ed571 in _dlerror_run (operate=operate@entry=0x7ffff75eceb0 <dlopen_doit>, args=args@entry=0x7fffffffd1a0) at dlerror.c:163
#11 0x00007ffff75ecfa1 in __dlopen (file=<optimized out>, mode=<optimized out>) at dlopen.c:87
#12 0x000000000051bb39 in _PyImport_GetDynLoadFunc ()
<snip>

好吧,有很多事情要处理,但让我们专注于真正重要的那一行:

#1  0x00007ffff0f3247a in _GLOBAL__sub_I_logging.cc () from prefix/lib/libcaffe2.so

这是对 logging.cc(它是 GLog 的一部分)中全局变量的构造函数的调用。如您所见,此调用位于 libcaffe2.so 中,这意味着 GLog 已静态链接到 libcaffe2.so [我使用的是 caffe2,但此过程对两者应该相同]。

然后,您可以设置断点google::(anonymous namespace)::FlagRegistry::RegisterFlag并从头开始重新运行程序。查看对 RegisterFlag() 的每次调用,并找出第一次注册此特定标志的位置。如果提供标志的库是共享库,那么它应该只从该 .so 文件中注册,而不是其他任何地方。

要确认诊断,您可以使用

nm <library> | grep _GLOBAL__sub_I_logging.cc

检查库文件中的该初始化函数。一旦你找到了罪魁祸首,你就需要重建它,这样它就不会静态链接到 GFlags/GLog。

于 2019-06-11T20:20:36.067 回答
1

我还安装了两个库,一个共享的 .so 库和一个静态的 .a 库。我删除了它们以及 /usr/local/include/glog 文件夹。我(交叉)编译系统时带来的 .so 文件,而 .a 来自本机和最新版本。最终,它归结为以提供 .so 文件的方式(本地)构建 glog。我从一个干净的下载开始:

git clone git://github.com/google/glog

然后我编辑了 CMakeLists.txt。它在哪里说:

add_library (glog
  ${GLOG_SRCS}
)

我将其更改为:

add_library (glog SHARED
  ${GLOG_SRCS}
)

接下来,您应该能够按照其他说明进行操作。对于我的特殊情况,我不得不使用稍微不同的指令,而不是说你必须这样做。对我来说是: mkdir build cd build

export CXXFLAGS="-fPIC"
cmake ..
make
sudo make install

这给了我 .so 文件并将它们放在正确的位置。然后我重新开始使用 caffe,它为我修复了错误。

于 2015-11-05T17:06:12.433 回答