在Ubuntu 12.04中的Python 2.7中导入Tensorflow时出错。 “找不到GLIBC_2.17”
python
tensorflow
9
0

我已经使用python成功安装了Tensorflow绑定。但是,当我尝试导入Tensorflow时,出现以下错误。

ImportError: /lib/x86_64-linux-gnu/libc.so.6: version `GLIBC_2.17' not found (required by /usr/local/lib/python2.7/dist-packages/tensorflow/python/_pywrap_tensorflow.so)

我试图将GLIBC_2.15更新为2.17,但是没有运气。

参考资料:
Stack Overflow
收藏
评论
共 5 个回答
高赞 时间 活跃

我尝试了BR_User解决方案 ,但仍然很烦人:

ImportError: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.14' not found

我使用的是CentOS 6.7,它也缺少更新的c ++标准库,因此要以BR_User解决方案为基础,我提取了正确的libstdc ++软件包,但是我发现不需要虚拟环境。

假设您已经安装了tensorflow,它会给出:

mkdir ~/my_libc_env
cd ~/my_libc_env
wget http://launchpadlibrarian.net/137699828/libc6_2.17-0ubuntu5_amd64.deb
wget http://launchpadlibrarian.net/137699829/libc6-dev_2.17-0ubuntu5_amd64.deb
wget ftp.riken.jp/Linux/scientific/7.0/x86_64/os/Packages/libstdc++-4.8.2-16.el7.x86_64.rpm
ar p libc6_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
ar p libc6-dev_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
rpm2cpio libstdc++-4.8.2-7mgc30.x86_64.rpm| cpio -idmv

然后使用以下命令运行python:

LD_LIBRARY_PATH="$HOME/my_libc_env/lib/x86_64-linux-gnu/:$HOME/my_libc_env/usr/lib64/" $HOME/my_libc_env/lib/x86_64-linux-gnu/ld-2.17.so `which python`

如果不起作用,我还有另一种解决方案 ,但是您不喜欢它。

收藏
评论

好的,这是我在上一个答案中提到的另一个解决方案,它比较棘手,但是应该始终在GLIBC> = 2.12和GLIBCXX> = 3.4.13的系统上运行。就我而言,它使用的是CentOS 6.7,但对于Ubuntu 12.04也很好。

我们将需要在另一台计算机上或单独安装的gcc版本支持c ++ 11。但暂时不。

我们在这里要做的是编辑_pywrap_tensorflow.so二进制文件,以“弱化”其libc和libstdc ++依赖项,以便ld接受链接我们将要创建的存根。然后我们将这些存根用于缺少的符号,最后在运行python时要预加载所有这些。

首先,我要感谢詹姆斯的出色文章( http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc )和宝贵的建议,没有他,我无法做到。

因此,让我们从弱化依赖关系开始,这只是替换_pywrap_tensorflow.so中的正确字节。请注意,此步骤仅适用于当前版本的tensorflow(0.6.0)。因此,如果尚未完成,请创建并激活您的virtualenv (如果您不是admin virtualenv是一种解决方案,则另一种方法是在--pip命令中添加--user标志),然后安装tensorflow 0.6.0(将cpu替换为如果需要gpu版本,请在网址中添加gpu):

pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.6.0-cp27-none-linux_x86_64.whl

让我们减弱所有烦人的依赖性,这是用于tensorflow的cpu版本的命令:

TENSORFLOW_DIR=`python -c "import imp; print(imp.find_module('tensorflow')[1])"`
for addr in 0xC6A93C 0xC6A99C 0xC6A9EC 0xC6AA0C 0xC6AA1C 0xC6AA3C; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so bs=1 seek=$((addr)) ; done

这是gpu之一(仅运行正确的一个,否则您将破坏二进制文件):

TENSORFLOW_DIR=`python -c "import imp; print(imp.find_module('tensorflow')[1])"`
for addr in 0xDC5EA4 0xDC5F04 0xDC5F54 0xDC5F74 0xDC5F84 0xDC5FA4; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so bs=1 seek=$((addr)) ; done

您可以使用以下方法进行检查:

readelf -V ${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so

如果您想了解这里发生了什么,请看一下文章。

现在,我们将为缺少的libc符号制作存根:

mkdir ~/my_stubs
cd ~/my_stubs
MYSTUBS=~/my_stubs
printf "#include <time.h>\n#include <string.h>\nvoid* memcpy(void *dest, const void *src, size_t n) {\nreturn memmove(dest, src, n);\n}\nint clock_gettime(clockid_t clk_id, struct timespec *tp) {\nreturn clock_gettime(clk_id, tp);\n}" > mylibc.c
gcc -s -shared -o mylibc.so -fPIC -fno-builtin mylibc.c

需要在缺少依赖项的计算机上(或具有类似标准库版本的计算机(例如,在集群中))执行该步骤。

现在我们可能需要更换机器,因为我们需要一个支持c ++ 11的gcc,并且它可能不在缺少所有依赖项的机器上(或者您可以使用最新gcc的隔离安装)。在下面的内容中,我假设我们仍然在~/my_stubs并且您以某种方式在整个计算机上共享您的家,否则,您只需复制完成后将生成的.so文件。

因此,我们可以为libstdc ++做一个存根,对于剩下的遗漏,我们将从gcc源代码编译它们(可能需要一些时间来克隆存储库):

printf "#include <functional>\nvoid std::__throw_bad_function_call(void) {\nexit(1);\n}" > bad_function.cc
gcc -std=c++11 -s -shared -o bad_function.so -fPIC -fno-builtin bad_function.cc
git clone https://github.com/gcc-mirror/gcc.git
cd gcc
mkdir my_include
mkdir my_include/ext
cp libstdc++-v3/include/ext/aligned_buffer.h my_include/ext
gcc -I$PWD/my_include -std=c++11 -fpermissive -s -shared -o $MYSTUBS/hashtable.so -fPIC -fno-builtin libstdc++-v3/src/c++11/hashtable_c++0x.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/chrono.so -fPIC -fno-builtin libstdc++-v3/src/c++11/chrono.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/random.so -fPIC -fno-builtin libstdc++-v3/src/c++11/random.cc
gcc -std=c++11 -fpermissive -s -shared -o $MYSTUBS/hash_bytes.so -fPIC -fno-builtin ./libstdc++-v3/libsupc++/hash_bytes.cc

就是这样!您现在可以通过预加载我们所有共享库(和您的本地libstdc ++)来运行tensorflow python脚本:

LIBSTDCPP=`ldconfig -p | grep libstdc++.so.6 | grep 64 | cut -d' ' -f4` #For 64bit machines
LD_PRELOAD="$MYSTUBS/mylibc.so:$MYSTUBS/random.so:$MYSTUBS/hash_bytes.so:$MYSTUBS/chrono.so:$MYSTUBS/hashtable.so:$MYSTUBS/bad_function.so:$LIBSTDCPP" python ${TENSORFLOW_DIR}/models/image/mnist/convolutional.py

:)

收藏
评论

我遇到了同样的问题,因此在谷歌搜索中执行了以下步骤:

$ sudo pip install --upgrade virtualenv
$ virtualenv --system-site-packages ~/tensorflow
$ cd ~/tensorflow
$ source bin/activate
$ pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl
$ cd /tmp
$ wget http://launchpadlibrarian.net/137699828/libc6_2.17-0ubuntu5_amd64.deb
$ wget http://launchpadlibrarian.net/137699829/libc6-dev_2.17-0ubuntu5_amd64.deb
$ mkdir libc6_2.17
$ cd libc6_2.17
$ ar p ../libc6_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
$ ar p ../libc6-dev_2.17-0ubuntu5_amd64.deb data.tar.gz | tar zx
$ cd -
$ LD_LIBRARY_PATH=/tmp/libc6_2.17/lib/x86_64-linux-gnu/ /tmp/libc6_2.17/lib/x86_64-linux-gnu/ld-2.17.so bin/python local/lib/python2.7/site-packages/tensorflow/models/image/mnist/convolutional.py

并退出:

$ deactivate 

这对我行得通。

收藏
评论

我刚刚设法在具有glibc 2.12的CentOS 6.5上安装了tensorflow 0.12rc0,而没有root特权。简单地通过pip安装tensorflow二进制文件给我一个错误,也与GLIBC版本有关。

基本上,您有4个如何处理此问题的选项(每个都有优点和缺点):

选项1-全局升级系统GLIBC。

可能是最好的选择, 如果您的系统支持this ,则您具有root特权,并且您确信此升级不会由于某种奇怪的原因而破坏任何内容。最终,这取决于升级整个Linux发行版。 是流行发行版中默认GLIBC版本的简短清单。

选项2-将第二个GLIBC添加到您的系统

编译或下载二进制文件 。最简单直接的选择。特别是如果您只需要运行一些简单的脚本

  • 在同一系统上可以有多个版本的glibc,但应格外小心。
  • 如果所有更改都限于虚拟环境,则不会破坏系统。
  • 许多以前安装/编译过的程序可能都依赖于旧的GLIBC,它们在新环境(例如python IDE)中崩溃 。包括大多数基本的bash命令,例如“ lc”,“ cd”等。
  • 其他副作用,例如大量内存泄漏 ,也是可能的。
  • 因此, 将新的GLIBC添加到您的正常环境是一个非常糟糕的主意,例如通过.bashrc
  • 另一方面,如果您需要在新的虚拟环境中使用某些特定工具,则可以针对新的GLIBC进行重新编译 。因此,它将在您的新环境中正常运行。
  • 但是,就我个人而言,我很快放弃了在新环境中(无需root和程序包管理器)重新编译所需的一切。
  • GLIBC开发人员正式提供了一种略有不同的方法来测试新的GLIBC版本。

选项3-补丁张量流

可能适用于TF 0.6.0,但是当每个新的Tensorflow版本发布时,您可能必须从头开始。例如, 这里的修正为0.9.0。

选项4-从源代码编译张量流

如果您从源代码重新编译它并链接到现有的GLIBC,则不再需要更新的GLIBC。不知何故,这里没有任何答案提到此选项。恕我直言,这是最好的选择,无论是“ 一般 ”还是“专门用于张量流”。

  • 这可以在r0.11上正常运行,并且可能会使用数年,但是从理论上讲,如果他们决定实际使用某些新的GLIBC功能(而不是旧版本中的功能),则它可能会在某些新的tensorflow版本中中断。
  • 老实说,从源代码构建张量流并不是一件容易的事,尤其是在过时的系统上。

“在过时的系统上构建张量流”的快速摘要:

尽管官方指南提供了“ 从源代码安装 ”部分,但是您需要执行一些技巧才能在过时的系统上进行构建。在这里,我假设您没有root特权(如果有的话-您可能可以使用包管理器安装相同的预请求,而可以从源代码手动构建它们)。

我发现了两个有据可查的成功案例: #1#2和官方github上的许多有用文章(主要是一些链接到二进制文件内部的库): #1#2#3#4 。我必须结合技巧,在那里成功地编译了TF。

  1. 首先,检查您的gcc --version ,并验证它是否支持c ++ 11。我的是4.4.7,所以它行不通。我已经下载了 gcc-4.9.4源代码,并对其进行了编译 。此步骤非常简单,但是编译本身可能需要几个小时。作为解决bazel问题的方法,我编译了gcc,其中包含到asldnm 硬编码路径 。但是,您可以尝试另一种解决方法:( 12 )。

     #!/bin/sh unset LIBRARY_PATH CPATH C_INCLUDE_PATH unset PKG_CONFIG_PATH CPLUS_INCLUDE_PATH INCLUDE LD_LIBRARY_PATH cd gcc-4.9.4 ./contrib/download_prerequisites mkdir objdir cd objdir # I've added --disable-multilib to fix the following error: # /usr/bin/ld: crt1.o: No such file: No such file or directory # collect2: ld returned 1 exit status # configure: error: I suspect your system does not have 32-bit # developement libraries (libc and headers). If you have them, # rerun configure with --enable-multilib. If you do not have them, # and want to build a 64-bit-only compiler, rerun configure # with --disable-multilib. ../configure --prefix=$HOME/opt/gcc-4.9.4 \ --disable-multilib \ --disable-nls \ --enable-languages=c,c++ \ --with-ld=/usr/bin/ld \ --with-nm=/usr/bin/nm \ --with-as=/usr/bin/as make make install 
  2. 检查您的java --version 。 Bazel需要JDK 8,如有必要,请安装它。 (他们仍然为bazel-0.4.1 提供一些与jdk7相关的下载,但看起来他们认为它已弃用)

  3. 我创建了一个单独的use_gcc_4.9.4.sh文件,其中包含必要的环境变量。当我需要与这个较新的编译器相关的东西时,我使用source ./use_gcc_4.9.4.sh

     #!/bin/sh this=$HOME/opt/gcc-4.9.4 export PATH=$this/bin:$PATH export CPATH=$this/include:$CPATH export LIBRARY_PATH=$this/lib:$LIBRARY_PATH export LIBRARY_PATH=$this/lib64:$LIBRARY_PATH export LD_LIBRARY_PATH=$this/lib:$LD_LIBRARY_PATH export LD_LIBRARY_PATH=$this/lib64:$LD_LIBRARY_PATH 
  4. 当前的bazel二进制文件(0.4.1) 需要GLIBC 2.14 ,因此我们也必须从源代码编译bazel (使用新的gcc)。正常运行,除非只允许在目标计算机上运行非常有限数量的线程 。 ( 这篇文章介绍了一些其他解决方法,但在我看来,它们是不需要的,可能是由于bazel代码的最新更新。)

  5. 获取tensorflow源代码git clone https://github.com/tensorflow/tensorflow ,并安装所需的先决条件(CUDA,cuDNN,python等)。参见官方指南

  6. 如果您未使用默认系统gcc(例如,如上所述,如果您必须编译较新的gcc),则将以下链接器标志添加到tensorflow/third_party/gpus/crosstool/CROSSTOOL.tpl 第59行

     linker_flag: "-L/home/username/localinst/opt/gcc-4.9.4/lib64" linker_flag: "-Wl,-rpath,/home/username/localinst/opt/gcc-4.9.4/lib64" 

    如果没有这一步,你可能会遇到这样的错误消息这样

     # ERROR: /home/username/localdistr/src/tensorflow/tensorflow/tensorflow/core/debug/BUILD:33:1: null failed: protoc failed: error executing command bazel-out/host/bin/external/protobuf/protoc '--cpp_out=bazel-out/local_linux-py3-opt/genfiles/' '--plugin=protoc-gen-grpc=bazel-out/host/bin/external/grpc/grpc_cpp_plugin' ... (remaining 8 argument(s) skipped): com.google.devtools.build.lib.shell.BadExitStatusException: Process exited with status 1. # bazel-out/host/bin/external/protobuf/protoc: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.20' not found (required by bazel-out/host/bin/external/protobuf/protoc) # bazel-out/host/bin/external/protobuf/protoc: /usr/lib64/libstdc++.so.6: version `CXXABI_1.3.8' not found (required by bazel-out/host/bin/external/protobuf/protoc) # bazel-out/host/bin/external/protobuf/protoc: /usr/lib64/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by bazel-out/host/bin/external/protobuf/protoc) 
  7. 最后,为了避免依赖GLIBC,我们必须通过添加-lrt链接器标志( 也可能是 -lm )来静态链接某些库。我发现了多个帖子,建议以其他方式添加它:

    没有-lrt我再次遇到特定于GLIBC版本的错误,尝试import tensorflow

     # ImportError: /lib64/libc.so.6: version `GLIBC_2.14' not found (required by /home/username/anaconda3/envs/myenvname/lib/python3.5/site-packages/tensorflow/python/_pywrap_tensorflow.so) 

    没有-lm您可能会遇到这个问题 (对我来说,这是不必要的)。

  8. 运行构建过程。

    source ./use_gcc_4.9.4.sh
    ./configure
    bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
    bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
    pip install --upgrade /tmp/tensorflow_pkg/tensorflow-0.12.0rc0-cp35-cp35m-linux_x86_64.whl
  1. 尝试运行以下简单的python脚本以测试最基本的功能是否正常运行:

     import tensorflow as tf hello = tf.constant('Hello, TensorFlow!') sess = tf.Session() print(sess.run(hello)) a = tf.constant(10) b = tf.constant(32) print(sess.run(a + b)) 
收藏
评论

请注意Theo Trouillon的“弱化”解决方案。它仅适用于Tensorflow 0.6.0。如果您想将其应用于Tensorflow 0.9.0,它将变得更加棘手。我的情况是CPU模式Centos 6.7,其中GLIBC 2.12 GLIBCXX 3.4.13。

安装tensorflow:

pip uninstall protobuf 
pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0-cp27-none-linux_x86_64.whl

“弱化”代码应更改为:

TENSORFLOW_DIR=`python -c "import imp; print(imp.find_module('tensorflow')[1])"`
for addr in 0x376e34 0x376e94 0x376ef4 0x376f14 0x376f24 0x376f44 0x376f54 ; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/python/_pywrap_tensorflow.so bs=1 seek=$((addr)) ; done
for addr in 0x93aa4 0x93b04 ; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/contrib/layers/python/ops/_bucketization_op.so bs=1 seek=$((addr)) ; done
for addr in 0x95bec 0x95c4c ; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/contrib/layers/python/ops/_sparse_feature_cross_op.so bs=1 seek=$((addr)) ; done
for addr in 0x9ffec 0x9fffc 0xa005c ; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/contrib/metrics/python/ops/_set_ops.so bs=1 seek=$((addr)) ; done
for addr in 0x96aa4 0x96b04 0x96b24; do printf '\x02' | dd conv=notrunc of=${TENSORFLOW_DIR}/contrib/linear_optimizer/python/ops/_sdca_ops.so bs=1 seek=$((addr)) ; done

并且以下代码应添加到在较新计算机上生成代码的存根中。

mkdir my_include/bits
cp libstdc++-v3/include/bits/shared_ptr_atomic.h my_include/bits/
cp libstdc++-v3/include/std/memory my_include/
gcc -I$PWD/my_include -std=c++11 -fpermissive -s -shared -o ${MYSTUBS}/shared_ptr.so -fPIC -fno-builtin ./libstdc++-v3/src/c++11/shared_ptr.cc
gcc -I$PWD/my_include -std=c++11 -fpermissive -s -shared -o ${MYSTUBS}/list.so -fPIC -fno-builtin ./libstdc++-v3/src/c++98/list.cc
echo "
#include <unistd.h>
#include <stdlib.h>
char * secure_getenv (const char *name) {
          if ((getuid () == geteuid ()) && (getgid () == getegid ())) return getenv (name); else  return NULL;
}" > getenv.cc
gcc -I$PWD/my_include  -std=c++11 -fpermissive -s -shared -o    ${MYSTUBS}/getenv.so -fPIC -fno-builtin getenv.cc

当然,最终的运行代码应该更改为包括其他存根。

LD_PRELOAD="$MYSTUBS/list.so:$MYSTUBS/mylibc.so:$MYSTUBS/shared_ptr.so:$MYSTUBS/getenv.so:$MYSTUBS/random.so:$MYSTUBS/hash_bytes.so:$MYSTUBS/chrono.so:$MYSTUBS/hashtable.so:$MYSTUBS/bad_function.so:$LIBSTDCPP" python  ${TENSORFLOW_DIR}/models/image/mnist/convolutional.py
收藏
评论
新手导航
  • 社区规范
  • 提出问题
  • 进行投票
  • 个人资料
  • 优化问题
  • 回答问题