首页 星云 工具 资源 星选 资讯 热门工具
:

PDF转图片 完全免费 小红书视频下载 无水印 抖音视频下载 无水印 数字星空

解决auditwheel repair过程rpath被修改的问题

编程知识
2024年09月03日 08:34

问题背景

AuditWheel是一个用于修复Python的whl包的工具,例如在这个CyFES开源库中,因为使用到了Cython和CUDA编译动态链接库的技术,方便Python调用。但是在编译CUDA算子时如果使用到了运行时库,那么在第一步构建whl包的时候不会自动包含运行时库,而第二步使用auditwheel进行whl包修复的时候,会自动把运行时库相关的动态链接库拷贝到whl包中。首先看一下修复前的whl包的目录树:

$ unzip -l dist/CyFES-2.7-cp37-cp37m-linux_x86_64.whl 
Archive:  dist/CyFES-2.7-cp37-cp37m-linux_x86_64.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
     2071  2024-09-02 07:54   CyFES-2.7.data/data/cyfes/FES.cuh
     1731  2024-08-27 02:47   CyFES-2.7.data/data/cyfes/FES_f32.cuh
   692112  2024-09-02 09:38   CyFES-2.7.data/data/cyfes/libcufes.1.so
    55472  2024-09-02 09:38   CyFES-2.7.data/data/cyfes/libcufes.so
     1628  2024-09-02 07:54   cyfes/__init__.py
     6117  2024-09-02 07:54   cyfes/__main__.py
     3632  2024-08-16 06:52   cyfes/utils.py
  1457723  2024-09-02 09:38   cyfes/wrapper.c
  1545248  2024-09-02 09:38   cyfes/wrapper.cpython-37m-x86_64-linux-gnu.so
  1245635  2024-09-02 09:38   cyfes/wrapper_f32.c
  1213984  2024-09-02 09:38   cyfes/wrapper_f32.cpython-37m-x86_64-linux-gnu.so
     2071  2024-09-02 07:54   cyfes/kernels/FES.cuh
     1731  2024-08-27 02:47   cyfes/kernels/FES_f32.cuh
        0  2024-08-29 07:45   cyfes/kernels/__init__.py
     1063  2024-09-02 09:38   CyFES-2.7.dist-info/LICENSE
     5588  2024-09-02 09:38   CyFES-2.7.dist-info/METADATA
      104  2024-09-02 09:38   CyFES-2.7.dist-info/WHEEL
        6  2024-09-02 09:38   CyFES-2.7.dist-info/top_level.txt
     1569  2024-09-02 09:38   CyFES-2.7.dist-info/RECORD
---------                     -------
  6237485                     19 files

这里只有动态编译构建过程中生成的libcufes.sowrapper动态链接库文件。再看看使用auditwheel repair修复之后的whl包目录树结构:

$ unzip -l fix-dist/CyFES-2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl 
Archive:  fix-dist/CyFES-2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  Length      Date    Time    Name
---------  ---------- -----   ----
        0  2024-09-02 09:39   cyfes/
        0  2024-09-02 09:39   CyFES-2.7.data/
        0  2024-09-02 09:39   CyFES-2.7.dist-info/
        0  2024-09-02 09:39   CyFES.libs/
        0  2024-09-02 09:39   cyfes/kernels/
  1457723  2024-09-02 09:39   cyfes/wrapper.c
  1213984  2024-09-02 09:39   cyfes/wrapper_f32.cpython-37m-x86_64-linux-gnu.so
     6117  2024-09-02 09:39   cyfes/__main__.py
  1564760  2024-09-02 09:39   cyfes/wrapper.cpython-37m-x86_64-linux-gnu.so
     1628  2024-09-02 09:39   cyfes/__init__.py
     3632  2024-09-02 09:39   cyfes/utils.py
  1245635  2024-09-02 09:39   cyfes/wrapper_f32.c
        0  2024-09-02 09:39   cyfes/kernels/__init__.py
     2071  2024-09-02 09:39   cyfes/kernels/FES.cuh
     1731  2024-09-02 09:39   cyfes/kernels/FES_f32.cuh
        0  2024-09-02 09:39   CyFES-2.7.data/data/
        0  2024-09-02 09:39   CyFES-2.7.data/data/cyfes/
    63696  2024-09-02 09:39   CyFES-2.7.data/data/cyfes/libcufes.so
   692112  2024-09-02 09:39   CyFES-2.7.data/data/cyfes/libcufes.1.so
     2071  2024-09-02 09:39   CyFES-2.7.data/data/cyfes/FES.cuh
     1731  2024-09-02 09:39   CyFES-2.7.data/data/cyfes/FES_f32.cuh
      150  2024-09-02 09:39   CyFES-2.7.dist-info/WHEEL
     1063  2024-09-02 09:39   CyFES-2.7.dist-info/LICENSE
     1784  2024-09-02 09:39   CyFES-2.7.dist-info/RECORD
        6  2024-09-02 09:39   CyFES-2.7.dist-info/top_level.txt
     5588  2024-09-02 09:39   CyFES-2.7.dist-info/METADATA
   523312  2024-09-02 09:39   CyFES.libs/libcudart-80664282.so.10.2.89
   168192  2024-09-02 09:39   CyFES.libs/libgomp-a34b3233.so.1.0.0
---------                     -------
  6956986                     28 files

在这个新的结构中,auditwheel自动把依赖的cudart运行时库和omp分布式库拷贝到了whl包中。这样在本地安装之后,会在site-packages路径下找到一个CyFES.libs的目录,其中就存储了相关的两个动态链接库。那么接下来问题就出现了,在使用$ python3 setup.py sdist bdist_wheel --universal构建的时候,动态链接库libcufes.so是有rpath的,但是使用auditwheel修复之后,rpath消失了:

$ python3 -m auditwheel lddtree build/cyfes/libcufes.so
INFO:auditwheel.main_lddtree:{
    "interp": null,
    "path": "build/cyfes/libcufes.so",
    "realpath": "build/cyfes/libcufes.so",
    "needed": [
        "libcudart.so.10.2",
        "librt.so.1",
        "libpthread.so.0",
        "libdl.so.2",
        "libstdc++.so.6",
        "libm.so.6",
        "libgcc_s.so.1",
        "libc.so.6"
    ],
    "rpath": [],
    "runpath": [],

或者也可以使用$ patchelf --print-rpath xxx.so来查看动态链接库的rpath路径。

解决方案

首先我们梳理一下思路。如果这个问题不修复,那么导致的直接结果是,使用$ python3 -m pip install xxx.whl之后,安装过程不报错,但是调用相关函数时会出现段错误的报错。出现这个错误的根本原因是找不到相应的cudart和omp动态链接库。如果不使用auditwheel修复的话,这个包是不完整的,应用在不同版本的cuda上有可能报错。那么解决问题的方向应该是,让libcufes.so能够准确的找到auditwheel拷贝cudart和omp动态链接库文件的位置,也就是site-packages/CyFES.libs/。有了思路再看怎么实现的问题,首先是可以通过Makefile配置相关的运行时路径。换句话说,就是运行或者调用libcufes.so文件时会索引到的路径,只要把这个路径配置到cudart和omp所在路径,就可以索引到相关的库,也就不会报错。还有一种解决方案是,在编译构建完成后,通过patchelf工具直接修改libcufes.so动态链接库的rpath。

因为CyFES毕竟是一个Python库,综合考虑下来,在setup.py文件中配置patchelf命令是一个不错的选项。还有三个需要注意的点:

  1. 不同的Python版本,site-packages路径是不一样的;
  2. 不能使用绝对路径配置rpath;
  3. auditwheel修复whl包时会同时修改目标文件的rpath列表中的第一个路径。

针对于第一个问题,我们只要把支持的几个Python路径都配置上就可以了,例如把rpath配置为/lib/python3.7/site-packages/CyFES.libs:/lib/python3.8/site-packages/CyFES.libs,这样就支持了两个版本的Python路径。对于第二个问题,我们可以在rpath中使用$ORIGIN相对路径,也就是文件所在的当前位置。在安装cyfes时,会产生三个路径下的文件,分别存放data、lib和核心文件。其中lib与核心文件目录都在site-packages/路径下。因而彼此之间的相对路径索引形式是固定的,也就可以固定写在setup.py中进行配置。第三个问题,也很容易解决,只要在rpath的第一个位置放一个无用路径,随便它怎么改。最终形成的指令是这样的:

$ patchelf --set-rpath $ORIGIN:$ORIGIN/../lib/python3.7/site-packages/CyFES.libs:$ORIGIN/../lib/python3.8/site-packages/CyFES.libs:$ORIGIN/../lib/python3.9/site-packages/CyFES.libs:$ORIGIN/../lib/python3.10/site-packages/CyFES.libs libcufes.so

这样就可以解决libcufes.so动态链接库的rpath被auditwheel修改的问题,经过测试可以正常索引到相关的CUDA运行时和omp的动态链接库。

总结概要

在开源Python项目中,如果使用到了Cython或者CUDA C++等需要编译的后端技术,那么要传到pypi上就需要经过一个PEP标准的审查。要通过审查,就要经过多个版本的Python的构建,以及auditwheel修复的过程。本文解决了一个auditwheel修复过程中有可能出现的rpath路径索引问题。

版权声明

本文首发链接为:https://www.cnblogs.com/dechinphy/p/auditwheel.html

作者ID:DechinPhy

更多原著文章:https://www.cnblogs.com/dechinphy/

请博主喝咖啡:https://www.cnblogs.com/dechinphy/gallery/image/379634.html

From:https://www.cnblogs.com/dechinphy/p/18393854/auditwheel
本文地址: http://shuzixingkong.net/article/1684
0评论
提交 加载更多评论
其他文章 WPF性能优化之UI虚拟化
@目录前言一、VirtualizingStackPanel1.1 虚拟化功能介绍1、在Window中添加一个ListBox控件。2、在设计视图中用鼠标选中ListBox控件并右健依次单击“编辑其他模板”-“编辑项的布局模板”-“编辑副本”。3、查看生成的模板代码。1.2 虚拟化参数介绍二、Custo
WPF性能优化之UI虚拟化 WPF性能优化之UI虚拟化 WPF性能优化之UI虚拟化
新手入门 | 搭建 AI 模型开发环境
目录安装显卡驱动和开发库对于 Tesla 系列显卡对于 N 卡安装 CUDA 和 cuDNN安装 Miniconda安装 PyTorch 和 Transformers使用 Modelscope 下载加载模型PyCharm 项目配置模型加载和对话CPU 和 GPU 问题transformers 版本错
新手入门 | 搭建 AI 模型开发环境 新手入门 | 搭建 AI 模型开发环境 新手入门 | 搭建 AI 模型开发环境
省钱的开源项目「GitHub 热点速览」
本期,我从上周的热门开源项目中挑选了 5 个既省钱又省事,还好玩的开源项目。 首先,推荐的是省钱的电动汽车智能充电管理平台 evcc,它可以根据分时电价智能安排电动车充电时间,从而降低电费,如果你家还有太阳能充电和储能设备,evcc 更能最大限度地利用电能,让你的充电成本降到最低。说到省事,开源的
省钱的开源项目「GitHub 热点速览」 省钱的开源项目「GitHub 热点速览」 省钱的开源项目「GitHub 热点速览」
数据库中查询含有某个emoji表情的行数据
数据库中查询含有某个emoji表情的行数据 MySQL的情况 代码如下 ​ create table tt6(id int, name varchar(800)); insert into tt6 select 1, '121😊33'; insert into tt6
数据库中查询含有某个emoji表情的行数据 数据库中查询含有某个emoji表情的行数据 数据库中查询含有某个emoji表情的行数据
【VMware VCF】VCF 5.2:配置管理域 vSAN 延伸集群。
VMware vSAN 解决方案中,根据集群的配置类型分为 vSAN 标准集群、vSAN 延伸集群以及双主机集群(延伸集群特例)。我们最常见的使用方式应该是 vSAN 标准集群,也就是 vSAN HCI 超融合集群,至少由 3 台 ESXi 主机所组成,这些 ESXi 主机安装位属于同一个数据中内,
【VMware VCF】VCF 5.2:配置管理域 vSAN 延伸集群。 【VMware VCF】VCF 5.2:配置管理域 vSAN 延伸集群。 【VMware VCF】VCF 5.2:配置管理域 vSAN 延伸集群。
PlugIR:开源还不用微调,首尔大学提出即插即用的多轮对话图文检索 | ACL 2024
即插即用的PlugIR通过LLM提问者和用户之间的对话逐步改进文本查询以进行图像检索,然后利用LLM将对话转换为检索模型更易理解的格式(一句话)。首先,通过重新构造对话形式上下文消除了在现有视觉对话数据上微调检索模型的必要性,从而使任意黑盒模型都可以使用。其次,构建了LLM问答者根据当前情境中检索候
PlugIR:开源还不用微调,首尔大学提出即插即用的多轮对话图文检索 | ACL 2024 PlugIR:开源还不用微调,首尔大学提出即插即用的多轮对话图文检索 | ACL 2024 PlugIR:开源还不用微调,首尔大学提出即插即用的多轮对话图文检索 | ACL 2024
keycloak~scope客户端模板的使用
scope为何物? scope在oauth2中表示授权的范围,另外也可以理解为,根据认证时scope的参数,在构建jwt时,返回更多的信息;比如在keycloak中,你的可选scope(optional scope)中添加了address这个模板,当你通过/auth/realms/{realmId}
keycloak~scope客户端模板的使用 keycloak~scope客户端模板的使用 keycloak~scope客户端模板的使用
10 Python面向对象编程:类和对象以及和Java的对比
本篇是 Python 系列教程第 10 篇,更多内容敬请访问我的 Python 合集 这里只介绍类和对象,self、属性、方法、访问控制、类继承、方法重写在后面的文章里介绍 在Python中,类和对象是面向对象编程的基础。 1 类的概念 类是一种创建对象的蓝图或模板。它定义了一组属性(变量)和方法(