好的,这是我在之前的回答中提到的另一个解决方案,它更棘手,但应该始终适用于 GLIBC>=2.12 和 GLIBCXX>=3.4.13 的系统。在我的情况下,它是在 CentOS 6.7 上,但它也适用于 Ubuntu 12.04。
我们将需要一个支持 c++11 的 gcc 版本,无论是在另一台机器上还是独立安装;但暂时不是。
我们在这里要做的是编辑 _pywrap_tensorflow.so 二进制文件,以“弱化”它的 libc 和 libstdc++ 依赖项,以便 ld 接受链接我们要制作的存根。然后我们将为丢失的符号制作这些存根,最后我们将在运行 python 时预加载所有这些。
首先,我要感谢 James 的精彩文章 ( http://www.lightofdawn.org/wiki/wiki.cgi/NewAppsOnOldGlibc ) 和宝贵的建议,如果没有他,我不可能成功。
因此,让我们从弱化依赖关系开始,它只是替换 _pywrap_tensorflow.so 中的正确字节。请注意,此步骤仅适用于当前版本的 tensorflow (0.6.0)。因此,如果尚未创建并激活您的virtualenv(如果您不是管理员,则 virtualenv 是一种解决方案,另一种是在--user
pip 命令中添加标志),然后安装 tensorflow 0.6.0(将 cpu 替换为 gpu 中的url,如果你想要 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
:)