概述
https://zhuanlan.zhihu.com/p/444805518
背景:
目前 AI 算法开发特别是训练基本都以 Python 为主,主流的 AI 计算框架如 TensorFlow、PyTorch 等都提供了丰富的 Python 接口。
但由于 Python 属于动态语言,解释执行并缺少成熟的 JIT 方案,计算密集型场景多核并发受限等原因,很难直接满足较高性能要求的实时 Serving 需求。
GIL(Global Interpreter Lock)全局解释器锁:同一时刻在一个进程只允许一个线程使用解释器,导致多线程无法真正用到多核。由于持有锁的线程在执行到 I/O 密集函数等一些等待操作时会自动释放 GIL 锁,所以对于 I/O 密集型服务来说,多线程是有效果的。但对于 CPU 密集型操作,由于每次只能有一个线程真正执行计算,对性能的影响可想而知。
在一些对性能要求高的场景下,还是需要使用 C/C++来解决。但是如果要求算法同学全部使用 C++来开发线上推理服务,成本又非常高,导致开发效率和资源浪费。
如果有【轻便的方法】能将 Python 和部分 C++编写的核心代码结合起来,就能达到既保证开发效率又保证服务性能的效果。
轻便的方法——Pybind11
支持C++11 等新特性,Pybind11通过 C++ 编译时的自省来推断类型信息,来最大程度地减少传统拓展 Python 模块时繁杂的样板代码, 且实现了常见数据类型,如 STL 数据结构、智能指针、类、函数重载、实例方法等到 Python 的自动转换,其中函数可以接收和返回自定义数据类型的值、指针或引用。
业内来说,目前市面上大部分 AI 计算框架,如 TensorFlow、Pytorch、阿里 X-Deep Learning、百度 PaddlePaddle 等,均使用 pybind11 来提供 C++到 Python 端接口封装,其稳定性以及性能均已得到广泛验证。
MacOS环境安装:
检查最基本的python环境:
pip -V pip3 -V which pip which pip3 which python which python3
建议使用专门的python虚拟环境:
查看版本:virtualenv --version
到统一的一个自定义路径下(如/Users/yonglang/chy/PyEnv)创建环境名为“pybind11Env”的环境:
virtualenv pybind11Env cd pybind11Env source bin/activate # 激活并进入虚拟环境 or source activate pybind11Env or conda activate pybind11Env deactivate # 退出环境
# 删除环境 1.直接删除虚拟环境所在目录 2.conda remove -n your_name --all # 查看虚拟环境列表 conda env list conda info -e virtualenv --python=/usr/local/bin/python3.8 sfEnv
在虚拟环境中安装包,不要带sudo哈
说明:确保virtualenv
pip3 install -i https://mirrors.aliyun.com/pypi/simple virtualenv pip3 install -i https://mirrors.aliyun.com/pypi/simple virtualenvwrapper
安装pybind11 (可使用-i换源下载)
python3 -m pip install pybind11 #其他以来项 python3 -m pip install python3-dev brew uninstall cmake
C++暴露给Python调用
1. 创建一个example.cpp
#include <pybind11/pybind11.h> int add(int i, int j) { return i + j; } PYBIND11_MODULE(example, m) { m.doc() = "pybind11 example plugin"; // optional module docstring m.def("add", &add, "A function that adds two numbers"); }
2. 编译
需要指定文件编译
#mac g++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix` 或 g++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix) #linux g++ -O3 -Wall -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` example.cpp -o example`python3-config --extension-suffix`