Python3 交叉编译 numpy pandas scipy scikit-learn

1. 概述

由于需要将Python3.7 和一些软件包交叉编译到 armv7 平台硬件,如果是arm64位的系统,很多包都有预编译好的版本,可直接下载。本文主要在基于 crossenv(https://github.com/benfogle/crossenv)环境下交叉编译。

2. 编译环境搭建

  • 创建编译环境路径 /home/ym/python-build,创建 /home/ym/python-build/install路径用于安装主机编译后的python, 创建路径/home/ym/python-build/install-arm用于安装交叉编译的python。
  • 下载python3 源码到 home/ym/python-build, 并解压,下载路径https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
  • 编译主机安装 Docker 环境,不同的linux发行版本安装方式不同, Debian -> apt, Redhat -> yum,我安装的版本是
    在这里插入图片描述
  • 在编译路径下创建一个 Dockerfile 文件:
FROM ubuntu:18.04                                                                                                          
ENV TZ=Asia/Shanghai
ENV LANG=en_US.UTF-8RUN sed -i -e 's|archive.ubuntu.com|mirrors.tuna.tsinghua.edu.cn|g' \               -e 's|security.ubuntu.com|mirrors.tuna.tsinghua.edu.cn|g' \                    /etc/apt/sources.list            RUN apt update && apt install -y vim curl proxchains gcc \                           build-essential crossbuild-essential-armhf \              libsdl1.2-dev xterm mesa-common-dev zstd liblz4-tool libffi-dev \  cmake libssl-dev bc device-tree-compiler flex bison libncurses-dev \lzma liblzma-dev libbz2-dev gfortran libopenblas-dev liblapack-dev \gfortran-arm-linux-gnueabihfRUN rm -rf /etc/apt/apt.conf.d/docker-clean RUN mkdir -p /root/project                
WORKDIR /root   
CMD ["/bin/bash"]  
  • 基于 Dockerfile 构建容器
docker build -f Dockerfile -t ubuntu:python .
  • 运行容器,将编译路径python-build映射至容器路径/root/project路径下:
docker run -v /home/ym/python-build/:/root/project -it ubuntu:python

3. 编译主机版本 python

  • 进入python源码目录
./configure --prefix=/root/project/install && make && make install

4. 交叉编译目标板 python

  • 交叉编译 openssl
# Adapted from https://github.com/japaric/cross
set -exINSTALL_DIR=/root/project/openssl
mkdir -p $INSTALL_DIR
main() {local version=1.1.1llocal os=linux-armv4local triple=arm-linux-gnueabihf-local sysroot=$INSTALL_DIRlocal dependencies=(ca-certificatescurlm4makeperl)# NOTE cross toolchain must be already installedapt-get updatefor dep in ${dependencies[@]}; doif ! dpkg -L $dep; thenapt-get install --no-install-recommends -y $depfidonetd=$(mktemp -d)pushd $td[ -e ./openssl-$version.tar.gz ] || {curl -L https://www.openssl.org/source/openssl-$version.tar.gz -o ./openssl-$version.tar.gz}tar --strip-components 1 -xz -f ./openssl-$version.tar.gzAR=${triple}ar CC=${triple}gcc ./Configure \--prefix=${sysroot}/usr \--openssldir=${sysroot}/usr \shared \no-asm \$os \-fPIC \${@:4}make -j$(nproc)make install_sw# clean uppopdrm -rf $td#rm $0#cp /usr/local/arm/usr/lib/pkgconfig/* /usr/share/pkgconfig/}main "${@}"
  • 交叉编译 bzip2, zlib, lzma 这些包会被python内建模块识别调用,并被 pandas 所依赖,同时需要把 zlib, lzma的动态库拷贝到目标板内核库的路径下。
  • lzma 下载地址https://xz.tukaani.org/xz-utils/#releases
  • 交叉编译libffi, 该包与 python ctypes 模块关联,注意交叉编译完成后需要将安装后的内容拷贝到交叉工具链的路径下(cp -rfp libffi/* /usr/arm-linux-gnueabihf/),并在 Python 配置选项中指定--with-system-ffi参数,交叉编译时 Python 自动构建 ctypes 模块,测试发现通过 LIBS 变量指定不会生效。
  • 创建一个 config.site 文件:
ac_cv_file__dev_ptc=no
ac_cv_buggy_getaddrinfo=no
ac_cv_file__dev_ptmx=no
  • 清除 python 源码相关环境(make distclean),运行下面脚本交叉编译目标版本 python-target(armv7),安装到路径/root/project/install-arm
#!/bin/sh
CROSS_COMPILE=arm-linux-gnueabihf
export CC=$CROSS_COMPILE-gcc
export CXX=$CROSS_COMPILE-g++
export AR=$CROSS_COMPILE-ar
export STRIP=$CROSS_COMPILE-strip
export LD=$CROSS_COMPILE-ld
export RANLIB=$CROSS_COMPILE-ranlib
export READELF=$CROSS_COMPILE-readelf
export PATH=$PATH:/root/project/install/bin
export CONFIG_SITE=/root/project/config.sitecd Python-3.7.2 && ./configure --enable-optimizations --with-openssl=/root/project/openssl/usr --with-system-ffi \LDFLAGS="-L/root/project/bzip2-1.0.8 -L/root/project/zlib/lib -L/root/project/lzma/lib" \LIBS="-lbz2 -lz -llzma" \--host=arm-linux-gnueabihf \--build=x86_64-linux-gnu \--target=arm-linux-gnueabihf \--disable-ipv6 \--without-pydebug \--without-dtrace \--prefix=/root/project/install-arm
make -j4 && make install

到此如果编译过程中没有出错的话,交叉编译后的 python 应该可以直接在 目标板上工作了,在目标板上创建一个 python 目录,将 install-arm 中的文件全部拷贝至该路径中,构建一个软连接 ln -sf /python/bin/python3.7 /usr/bin/python,然后在控制运行 python 查看是否正常:
在这里插入图片描述

5. 通过 crossenv 交叉编译 numpy,pandas

  • 如果只是想交叉编译 numpy 或者 pandas, 看到这一小节就行了,其中pandas 依赖 numpy。如果还要编译其他包请用第六节脚本编译的方法交叉编译 numpy.
1. 在主机环境下安装 crossenvcd  /root/project/install/bin./pip3 install crossenv
2. 使用crossenv创建 python-target 编译的虚拟环境./python3 -m crossenv /root/project/install-arm/bin/python3.7 cross_venv
3. 激活虚拟环境. cross_venv/bin/activate
注意没有代理可使用国内镜像如 pip install xx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
4. 编译安装 numpybuild-pip -v install numpypip -v install numpy
5. 编译安装 pandasbuild-pip -v install pandaspip -v install pandas
注意pandas 依赖 dateutil,dateutil会使用目标板的时区信息,请检查目标板是否有 /usr/share/zoneinfo 和 /etc/localtime 文件,没有可能在导入 pandas 包时会报错,可将交叉编译后的 dateutil/zoneinfo/dateutil-zoneinfo.tar.gz 解压至 /usr/share/zoneinfo中,并创建软连接 ln -sf /usr/share/zoneinfo/Asia/Shanghai  /etc/localtime编译成功后可在 cross_venv/cross/lib/pythonVERSION/site-packages 路径下查看编译完后的包其中包主要分两类:1). package -> 对应包的实际文件2). package-VERSION-dist-info -> 包的信息 
6. 将对应的 package 拷贝到目标板 path/to/python/lib/pythonVERSION/site-package 路径下

在这里插入图片描述

  • 这里导入包的时候,可能会报一些库文件缺失,需要把对应的库拷贝到目标板库/lib的路径下。

6. 通过 crossenv 交叉编译 scikit-learn

  • 这里先列一下依赖项
  • scikit-learn:
    • NumPy
    • SciPy :
      • NumPy
      • openblas
    • joblib
    • threadpoolctl
  • 由于 SciPy 强依赖 numpy 中 openblas 包,openblas 是一个数学运算库,可用于加速 numpy 运算,如果只是单纯编译 numpy,那么 openblas 是一个可选项,但是如果需要编译 SciPy,openblas 就是一个强依赖项了,但是 openblas 是由 Fortran 语言编写,直接用 crossenv 环境编译会报错,下面用一个脚本来交叉编译 numpy 和 SciPy,编译之前,先用交叉工具链编译 openblas,并在虚拟环境中 build-pip/pip安装 Cython < 3 版本:
1. 确认以下几个包已安装apt-get install gfortran libopenblas-dev liblapack-dev -y
2. 安装 fortran 交叉编译工具apt-get install gfortran-arm-linux-gnueabihf
3. 交叉编译 OpenBLAS-0.3.22cd OpenBLAS-0.3.22 && make TARGET=ARMV7 HOSTCC=gcc BINARY=32 CC=arm-linux-gnueabihf-gcc FC=arm-linux-gnueabihf-gfortranmake TARGET=ARMV7 PREFIX=/root/project/openblas install
  • 交叉编译 scipy 脚本
#!/bin/bash####################
# Script to build numpy and scipy wheels for ARM. set -exOUTPUT=$PWD/output
WORKING=$OUTPUT/build
if [ ! -d "$WORKING" ];thenmkdir -p $WORKING
fiGFORTRAN=arm-linux-gnueabihf-gfortran
OPENBLAS_INSTALL_DIR=$PWD/openblasBUILD_PYTHON=$PWD/install/bin/python3
HOST_PYTHON=$PWD/install-arm/bin/python3NUMPY_URL=https://files.pythonhosted.org/packages/45/b7/de7b8e67f2232c26af57c205aaad29fe17754f793404f59c8a730c7a191a/numpy-1.21.6.zip
SCIPY_URL=https://files.pythonhosted.org/packages/a7/5c/495190b8c7cc71977c3d3fafe788d99d43eeb4740ac56856095df6a23fbd/scipy-1.3.3.tar.gz
NUMPY_VERSION=${NUMPY_URL##*/}
if [[ $NUMPY_VERSION =~ .zip* ]];thenNUMPY_DIR=${NUMPY_VERSION%%.zip*}
elif [[ $NUMPY_VERSION =~ .tar.gz* ]];thenNUMPY_DIR=${NUMPY_VERSION%%.tar.gz*}
fi
SCIPY_VERSION=${SCIPY_URL##*/}
SCIPY_DIR=${SCIPY_VERSION%%.tar.gz*}PYPI_MIRROR="-i http://pypi.douban.com/simple --trusted-host pypi.douban.com"
################################################################
# Set up crossenv
$BUILD_PYTHON -m pip install crossenv
CROSS_VENV=$PWD/install/bin/cross_venv
if [ ! -d "$CROSS_VENV" ];then$BUILD_PYTHON -m crossenv $HOST_PYTHON $CROSS_VENV
fi
. $CROSS_VENV/bin/activate
pip install wheel $PYPI_MIRRORBUILD_SITE=$PWD/install/bin/cross_venv/build/lib/python3.7/site-packages
CROSS_SITE=$PWD/install/bin/cross_venv/cross/lib/python3.7/site-packages################################################################
# Host-numpy
# Install so we get the libnpymath.a in the right place.
if [ ! -f "$NUMPY_VERSION" ];thencurl -OL $NUMPY_URL
fi
if [ ! -d "$NUMPY_DIR" ];thenif [[ $NUMPY_VERSION =~ .zip* ]];thenunzip $NUMPY_VERSIONelif [[ $NUMPY_VERSION =~ .tar.gz* ]];then tar xf $NUMPY_VERSIONfi
fi
cd $NUMPY_DIR
cat > site.cfg <<EOF
[openblas]
libraries = openblas
library_dirs = $OPENBLAS_INSTALL_DIR/lib
include_dirs = $OPENBLAS_INSTALL_DIR/include
extra_link_args = -lgfortran
EOF
F90=$GFORTRAN cross-python setup.py install
F90=$GFORTRAN cross-python setup.py bdist_wheel
cd ..################################################################
# Build-numpy. Need to patch _after_ install.
NUMPY_PIP_VERSION=${NUMPY_DIR##*-}
build-pip install -v numpy==$NUMPY_PIP_VERSION $PYPI_MIRROR
INI=$(find $BUILD_SITE -name 'npymath.ini')
LIBDIR=$(find $CROSS_SITE -path '*/numpy/core/lib')
INCDIR=$(find $CROSS_SITE -path '*/numpy/core/include')cat > $INI <<EOF
[meta]
Name=npymath
Description=Portable, core math library implementing C99 standard
Version=0.1[variables]
# Force it to find cross-build libs when we build scipy
libdir=$LIBDIR
includedir=$INCDIR[default]
Libs=-L\${libdir} -lnpymath
Cflags=-I\${includedir}
Requires=mlib[msvc]
Libs=/LIBPATH:\${libdir} npymath.lib
Cflags=/INCLUDE:\${includedir}
Requires=mlib
EOF#################################################################
# host-scipy
if [ ! -f "$SCIPY_VERSION" ];thencurl -OL $SCIPY_URL
fi
if [ ! -d "$SCIPY_DIR" ];thentar xf $SCIPY_VERSION
fi
cd $SCIPY_DIR
cat > site.cfg <<EOF
[openblas]
libraries = openblas
library_dirs = $OPENBLAS_INSTALL_DIR/lib
include_dirs = $OPENBLAS_INSTALL_DIR/include
extra_link_args = -lgfortran
EOFF90=$GFORTRAN python setup.py bdist_wheel
F90=$GFORTRAN cross-python setup.py install
cd ..
  • 交叉编译 scikit-learn: :
  • SciPy -> 先前利用脚本已经完成了交叉编译,现在使用 build-pip 安装 build 版本:
build-pip install -v scipy=1.3.3 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
  • joblib -> build-pip/pip 直接安装没有其他依赖
build-pip install joblib==0.11 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install joblib==0.11 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
  • threadpoolctl -> build-pip/pip 直接安装没有其他依赖
build-pip install threadpoolctl==2.0.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install threadpoolctl==2.0.0 -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
  • 安装 scikit-learn:
build-pip install -v scikit-learn==1.0.2 --no-build-isolation -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install -v scikit-learn==1.0.2 --no-build-isolation -i http://pypi.douban.com/simple --trusted-host pypi.douban.com

至此交叉编译全部完成,将对应的包拷贝到目标板查看
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/665974.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node.js-1

Node.js 简介 定义&#xff1a;Node.js 是一个跨平台 JavaScript 运行环境&#xff0c;使开发者可以搭建服务器端的 JavaScript 应用程序 为什么 Node.js 能执行 JS 代码&#xff1a; Chrome 浏览器能执行 JS 代码&#xff0c;依靠的是内核中的 V8引擎&#xff08;即&#x…

2024PMP考试新考纲-近年真题练一练和很详细解析(1)

前面的几十篇文章中&#xff0c;华研荟主要从PMP相关的教材&#xff08;PMBOK第六版、PMBOK第七版和敏捷实践指南》出发&#xff0c;分类介绍了相关的考试真题&#xff0c;并逐一作了比较详细的解析&#xff0c;部分典型题目还做了提醒和拓展&#xff0c;帮助大家做题的时候知其…

Leetcode的AC指南 —— 栈与队列 :1047.删除字符串中的所有相邻重复项

摘要&#xff1a; **Leetcode的AC指南 —— 栈与队列 &#xff1a;1047.删除字符串中的所有相邻重复项 **。题目介绍&#xff1a;给出由小写字母组成的字符串 S&#xff0c;重复项删除操作会选择两个相邻且相同的字母&#xff0c;并删除它们。 在 S 上反复执行重复项删除操作&a…

MATLAB计算多边形质心/矩心

前言&#xff1a;不规则四边形的中心 不规则四边形的出心有多种定义&#xff0c;以下是最常见的三种&#xff1a; 1.重心&#xff1a;重心是四边形内部所有顶点连线交点的平均位置。可以通过求解四个顶点坐标的平均值来找到重心。 2.质心&#xff1a;质心是四边形内部所有质点…

242. Valid Anagram(有效的字母异位词)

问题描述 给定两个字符串 s 和 t &#xff0c;编写一个函数来判断 t 是否是 s 的字母异位词。 注意&#xff1a;若 s 和 t 中每个字符出现的次数都相同&#xff0c;则称 s 和 t 互为字母异位词。 问题分析 此问题与383. Ransom Note(赎金信)类似&#xff0c;只是字符变为了…

Qt多语言翻译

Qt多语言翻译概述 Qt提供了非常简单易用的多语言翻译机制&#xff0c;其核心类为QTranslator.概括来说就是利用Qt的lupdate工具将项目中所有tr函数包裹的字符串提取到.ts文件中&#xff0c;然后使用Qt Linguist由专门的翻译人员对提取的.ts文件进行逐个单词短语的翻译工作. 翻译…

Qt中的线程与信号槽

小实践 mainwindow.h #ifndef MAINWINDOW_H #define MAINWINDOW_H // #pragma once #include <QMainWindow> #include"zthread.h"QT_BEGIN_NAMESPACE namespace Ui { class MainWindow; } QT_END_NAMESPACEclass ZThread;class MainWindow : public QMainWin…

docker入门教程之将应用程序容器化

将应用程序容器化 在本指南的其余部分中&#xff0c;您将使用在 Node.js 上运行的简单待办事项列表管理器。如果您不熟悉 Node.js&#xff0c;请不要担心。本指南不需要任何 JavaScript 经验。 先决条件 您已安装最新版本的 Docker Desktop。您已经安装了 Git 客户端。您可以…

java05 数组

一 概念介绍 指的是一种容器&#xff0c;可以同来存储同种数据类型的多个值。 但是数组容器在存储数据的时候&#xff0c;需要结合隐式转换考虑。 比如&#xff1a; 定义了一个int类型的数组。那么boolean。double类型的数据是不能存到这个数组中的&#xff0c; 但是byte类…

Orange3数据预处理(分组组件)

Group By是Orange3中一个非常有用的组件&#xff0c;它允许用户对数据集进行聚合操作&#xff0c;类似于SQL中的GROUP BY语句或Pandas库中的groupby方法。以下是Group By组件的一些核心功能介绍&#xff1a; 1. Mean (平均数): 数据值的总和除以数据项的数量&#xff0c;显示数…

Megatron-LM源码系列(七):Distributed-Optimizer分布式优化器实现Part2

1. 使用入口 DistributedOptimizer类定义在megatron/optimizer/distrib_optimizer.py文件中。创建的入口是在megatron/optimizer/__init__.py文件中的get_megatron_optimizer函数中。根据传入的args.use_distributed_optimizer参数来判断是用DistributedOptimizer还是Float16O…

C#,雅各布斯塔尔—卢卡斯(Jacobsthal Lucas Number)的算法与源代码

1 雅各布斯塔尔序列 雅各布斯塔尔序列是一个与斐波那契序列类似的加法序列&#xff0c;由递归关系JnJn-12Jn-2定义&#xff0c;初始项J00&#xff0c;J11。序列中的一个数字称为雅可布沙尔数。它们是卢卡斯序列Un&#xff08;P&#xff0c;Q&#xff09;的一种特殊类型&#x…

股票交易

这里尝试利用单调队列优化&#xff0c;这里不好直接用单调队列的原因是因为(以买为例)\(-ap[i]*k_1\)不是只与下标有关的 所以解决方案一&#xff1a;我们将下标变成一个整体&#xff0c;再把后面的代价换掉然后将与下标无关的直接提出去 解决方案二&#xff1a;利用“蚯蚓”那…

<设计模式>单例模式懒汉和饿汉

目录 一、单例模式概述 二、懒汉模式和饿汉模式 1.饿汉模式 1.1代码实现 1.2实现细节 1.3模式优劣 2.懒汉模式 2.1代码实现 2.2实现细节 2.3模式优劣 三、多线程下的线程安全问题 1.懒汉和饿汉线程安全问题分析 1.1安全的饿汉模式 1.2不安全的懒汉模式 2.懒汉线程…

YOLOv5算法进阶改进(15)— 引入密集连接卷积网络DenseNet

前言:Hello大家好,我是小哥谈。DenseNet(密集连接卷积网络)是一种深度学习神经网络架构,它在2017年由Gao Huang等人提出。DenseNet的核心思想是通过密集连接(dense connection)来促进信息的流动和共享。在传统的卷积神经网络中,每个层的输入只来自于前一层的输出。而在…

Linux下编译EtherCAT主站SOEM-1.4.1

目录 1、SOEM下载 2、CMake安装​​​​​​ 3、编译 环境&#xff1a;Ubuntu1604. 1、SOEM下载 最新版为SOEM-v1.4.0&#xff0c;可以从github下载地址&#xff1a; https://github.com/OpenEtherCATsociety/SOEM 2、CMake安装​​​​​​ 3、编译 解压文件&#xff0c…

WebSocket学习笔记以及用户与客服聊天案例简单实现(springboot+vue)

一&#xff1a;介绍&#xff1a; 二&#xff1a;http协议与websocket对比&#xff1a; 三&#xff1a;websocket协议&#xff1a; 四&#xff1a;实现&#xff1a; 4.1客户端&#xff1a; 4.2服务端&#xff1a; 五&#xff1a;案例&#xff1a; 环境&#xff1a;做一个书店…

分布式任务调度框架XXL-JOB详解

分布式任务调度 概述 场景: 如12306网站根据不同车次设置放票时间点&#xff0c;商品成功发货后向客户发送短信提醒等任务,某财务系统需要在每天上午10天前统计前一天的账单数据 任务的调度是指系统为了完成特定业务&#xff0c;基于给定的时间点&#xff0c;时间间隔&#…

onnx转换为rknn置信度大于1,图像出现乱框问题解决

前言 环境介绍&#xff1a; 1.编译环境 Ubuntu 18.04.5 LTS 2.RKNN版本 py3.8-rknn2-1.4.0 3.单板 迅为itop-3568开发板 一、现象 采用yolov5训练并将pt转换为onnx&#xff0c;再将onnx采用py3.8-rknn2-1.4.0推理转换为rknn出现置信度大于1&#xff0c;并且图像乱框问题…

【服务器】RAID(独立磁盘冗余阵列)

RAID&#xff08;独立磁盘冗余阵列&#xff09; 一、RAID的介绍二、RAID的分类#2-1 RAID 02-2 RAID 1#2-3 RAID 32-4 RAID 52-5 RAID 62-6 RAID 10(先做镜像&#xff0c;再做条带化)2-7 RAID 01&#xff08;先做条带&#xff0c;再做镜像&#xff09;2-8 RAID比较 三、磁盘阵列…