docker - 构建tensorflow 2.2.0 pip wheel文件,用于CentOS系统(旧libc)

标签 docker tensorflow build libc

介绍:
我必须使用动态链接的cuda库(特别是cudart.so)创建Tensorflow 2.2.0的pip wheel。为此,我目前正在使用tensorflow-dev docker镜像。
我能够构建tf wheel文件,并且能够在构建容器中安装和使用它。
问题:
问题是在CentOS服务器中导入生成的wheel文件时,出现以下错误:

ImportError: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by /home1/private/mavridis/Vineyard/tensorflowshared/test/lib64/python3.6/site-packages/tensorflow/python/_pywrap_tensorflow_internal.so)
环顾四周后,问题是由使用较新的libc的构建容器引起的:
ldd --version
ldd (Ubuntu GLIBC 2.27-3ubuntu1) 2.27
与旧版本的CentOS相比:
ldd --version
ldd (GNU libc) 2.17
预期行为:
已经尝试了'vanilla'tenorflow 2.2.0版本,没有问题,请使用pip安装:
pip install tensorflow==2.2.0
我希望自己的构建也能正常工作。
因此,我假设有一些配置选项或docker配置,以允许我在CentOS设置中使用docker内置的wheel文件,就像pip安装的版本一样。由于打算将这个wheel文件部署到我无法控制的设置中,因此涉及备用OS和/或libc替换的解决方案不适用。
构建配置:
在构建期间,我使用以下配置/命令行:
export TF_NEED_CUDA=1
export TF_USE_XLA=0
export TF_SET_ANDROID_WORKSPACE=0
export TF_NEED_OPENCL_SYCL=0
export TF_NEED_ROCM=0
bazel build --config=opt --config=cuda --output_filter=DONT_MATCH_ANYTHING --linkopt=-L/usr/local/cuda/lib64 --linkopt=-lcudart --linkopt=-static-libstdc++ //tensorflow/tools/pip_package:build_pip_package
关于使用的选项:
--output_filter = DONT_MATCH_ANYTHING:静音警告
--linkopt = -L / usr / local / cuda / lib64 --linkopt = -lcudart:cudart.so的动态链接
--linkopt = -static-libstdc++:静态链接libstc++作为libstc++也会导致libc错误,但是这对于libm是不可能的

最佳答案

I expected my own build to also work.


这种期望是(显然)不正确的。您的程序或库从GLIBC中需要的符号取决于您所调用的函数。
考虑以下程序:
int main() { exit(0); }
在GLIBC-2.30系统上编译/链接时,该程序仅取决于GLIBC_2.2.5(因为它不调用任何较新的符号)。
现在稍微更改程序:
int main() { gettid(); exit(0); }
再次编译/链接它,突然之间该程序现在需要GLIBC_2.30(因为gettid()被添加到GLIBC的位置),并且在具有较旧GLIBC的任何系统上均无法使用。

So i assume there is some configuration option or docker configuration


当然:您的Docker镜像必须具有不比目标系统新的GLIBC,即GLIBC-2.17。您当前的图片包含GLIBC-2.27(或更高版本)。
您需要一个不同的Docker镜像,并且您可能必须自己构建它,因为GLIBC-2.17是over 7 years old,并且比TensorFlow早了很多年。
更新:

What i don't understand is how come the pip tensorflow package (which i assumed was build with the docker image i am using) works with CentOS?


它偶然地起作用,就像我的第一个程序可以在CentOS上运行一样,而第二个程序却不能。

In short i wanted to generate a pip package that would work on 'any' linux/libc version


这是一个不可能实现的目标:Linux早于GLIBC,并且不可能构建一个可以在不包含GLIBC的Linux发行版和包含GLIBC的发行版上工作的单个程序包。
您必须在某处画一条线。 tensorflow-dev docker image的开发人员在GLIBC-2.27处划界。基于此镜像构建的软件包应在2.27或更高版本的任何系统上都可以使用,并且可能(但不完全保证)在较旧的系统上可以使用。

just like the pip installed version.


您声称pip安装版本没有“仅GLIBC-xx或更高版本”的要求,但事实并非如此。我有99.9%的把握至少需要GLIBC-2.14。
要查找软件包要求的GLIBC版本,请运行以下命令:
readelf -WV _pywrap_tensorflow_internal.so | grep GLIBC_

I assumed, the pip installed version was built using the publicly available tensorflow-devel docker image.


那很有可能。就像我说的那样,它恰好可以在CentOS上运行,但是细微的更改可能使其不再起作用。
更新2:

So running the readelf command as you suggested, does show the most recent required versions to be: - pip version: GLIBC_2.12 - mine : GLIBC_2.27 So from what i understand the pip version uses an older version even from CentOS, which explains why it works.


它不“使用”较旧的版本,而是使用可用的任何版本。
它需要最低版本2.12,而您的构建需要最低版本2.27。

How do they achieve this? Do they use a different image that has an older libc? If so, where can i get it? Or do they use the public image, but build with some bazel flag, that 'limits' symbols to the ones contained up to libc 2.12?


您仍然没有得到它。
程序所需的版本取决于您所调用的函数。在我的示例程序中,如果我仅调用exit,则我的程序需要版本2.2.5,但是如果我也调用gettid,则我的程序需要版本2.30。 注意:这两个程序是在具有相同标志的同一系统上构建的。
因此,没有:他们(很可能)没有使用其他Docker镜像,也没有使用“魔术”淡褐色标志。他们只是碰巧不调用任何需要GLIBC版本> 2.12的函数,而您做到了。
附言您可以找到哪些符号导致构建中的“不良”依赖关系,如下所示:
readelf -Ws  _pywrap_tensorflow_internal.so | egrep 'GLIBC_2.2[0-9]'
readelf -Ws  _pywrap_tensorflow_internal.so | egrep 'GLIBC_2.1[89]'
这将产生类似于(使用第二个程序)的输出:
readelf -Ws a.out | egrep 'GLIBC_2.[23][0-9]'
     2: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND gettid@GLIBC_2.30 (2)
    48: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND gettid@@GLIBC_2.30
上面的输出显示,二进制文件从GLIBC 2.20或更高版本中唯一需要的符号是gettid

关于docker - 构建tensorflow 2.2.0 pip wheel文件,用于CentOS系统(旧libc),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62536543/

相关文章:

Maven 安装时出现 Maven 构建错误

python - tf.gather 在使用自定义 softmax_loss 函数时超出范围,即使它不应该

amazon-ec2 - Docker隐藏调用容器的IP

r - 在 Docker 容器中自定义 RStudio 环境

docker - 找不到所需的文件

python - 导入错误 : cannot import name 'network' from 'tensorflow.python.keras.engine'

python - 使用 tensorflow 估计器和集线器创建暹罗网络

android - 未声明的标识符 'setfscreation' AOSP

c++ - cmake + xcode : error 'Build setting PRODUCT_NAME undefined'

java - Docker 化 Spring 应用程序