使用 Pybind11 的 C++ 到 Python 模块
作者:互联网
Python 永远是我的第一选择。但与 C/C++ 相比,它在速度、内存使用和能源消耗方面效率低下。当我开始使用暗网时,我开始了解 ctypes 库,它有助于在 python 中调用 c 函数。感觉很难将它用于 C++ 函数和类对象。我找到了一种使用 pybind11 实现此绑定的简单方法。
在这里我想展示如何使用 C++ 来提高我们使用 pybind11 的 python 项目的性能。我对堆排序算法进行了性能比较,结果包含在本文中。此外,我在这里解释了如何制作不透明类型,以防止 STL 数据类型(向量、地图等)和 Python 数据结构(列表、字典)之间的复制操作。
pybind11的安装
pybind11 的安装非常简单。Pybind11开发者推荐三种安装方式。我选择使用 pip 从 PyPI 安装。
pip 安装 pybind11
堆排序 C++
// cpp_sort.cpp # include <pybind11/pybind11.h> # include <pybind11/numpy.h> namespace py = pybind11; class cpp_ { public : int *a; 诠释n; cpp_ (py:: array_t < int > & arr){ // Numpy 数组模板 auto buf = arr. 请求();// 请求缓冲区描述符 a = ( int *)buf.ptr; n = buf.shape[ 0 ]; } int heapify ( int *a,int i, int n) {// 最大堆 intleft_child=2*i+1; intright_child= left_child+1; 最大整数=我; 诠释吨; if (left_child < n) {if(a[left_child]>a[i]){max=left_child;}} else{return 0;} if(right_child < n && a[right_child]>a[max]){max =right_child;} if(max!=i){t=a[i]; a[i]=a[max];a[max]=t; heapify(a,max,n);} 返回 0; } int 堆排序(){ 诠释我,吨; for ( i= int (n/ 2 ) -1 ;i>= 0 ;i--){ heapify (a,i,n); } // 一个一个地获取最大值 for ( i=n -1 ;i>= 0 ;i--){ t=a[ 0 ]; a[ 0 ]=a[i]; [i]=t; 堆化(a,0,i); } 返回 0 ; } }; PYBIND11_MODULE (cpp_sort,m ) { // cpp_sort 是模块名,m 是绑定接口 py:: class_ <cpp_>(m, "cpp_" ) // 将类作为 cpp_ 暴露给 python 。def (py::init<py:: array_t < int > &>()) // 暴露类构造函数,数组作为输入 。def ( "heapsort" , &cpp_::heapsort) // 从 cpp_ 类公开堆排序函数 。def_readwrite ( "array_size" , &cpp_::n); //暴露变量n,重命名为array_size }
py::array_t 模板有助于将某些数据类型的 Numpy 数组传递到 C++ 端。应该包含 pybind11/numpy.h 标头以获得此功能。cpp_ 构造函数将 py::array_t 作为参数。要通过引用传递,数组的 dtype 应该匹配,即 np.int32 与 C++ 中的 int 相同,否则,更改不应反映在 python 端。
PYBIND11_MODULE 是一个带有两个参数的宏,cpp_sort 是模块名称,它应该不带引号,下一个参数是 m,它是用于接口绑定的 py::module_ 类型。
此代码写在 cpp_sort.cpp 文件中。可以使用下面创建共享对象库的命令在 Linux 中编译上述 C++。
C++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) cpp_sort.cpp -o cpp_sort$(python3-config --扩展后缀)$(python3 -m pybind11 --includes) cpp_sort.cpp -o cpp_sort $(python3-config --extension-后缀)
python中的堆排序
#py_sort.py class py_ : # 传递 numpy 数组的构造函数 def __init__ ( self,a ): self.a=a self.n=a.shape[ 0 ] # 对于最大堆 def heapify ( self, n, i ): maxx = i left_child = 2 * i + 1 right_child = 2 * i + 2 if left_child < n and self.a[i] < self.a[left_child]: maxx = left_child if right_child < n and self.a[maxx] < self.a[right_child]: maxx= right_child if maxx != i: self.a[i],self.a[maxx] = self.a[maxx],self.a[i] self.heapify( n, maxx) def heapsort ( self ): # 逐一获取最大值 for i in range ( int (self.n/ 2 )- 1 , - 1 , - 1 ): self.heapify( self.n, i) for i in range (self.n- 1 , 0 , - 1 ): self.a[i], self.a[ 0 ] = self.a[ 0], self.a[i] self.heapify(i, 0 )