当前位置: 首页 > news >正文

Pybind11的使用

目录

  • 1. 引言
    • 1.1 Pybind11 简介
    • 1.2 为什么需要 Pybind11
  • 2. 使用 Pybind11 进行 C++ 与 Python 交互
    • 2.1 基本用法
    • 2.2 编译与生成共享库
      • 2.2.1 在 Linux 下编译
      • 2.2.2 在 macOS 下编译
      • 2.2.3 编译选项详解
    • 2.3 在 Python 中使用编译后的模块
  • 3. 高级用法与注意事项
    • 3.1 绑定类和复杂数据结构
    • 3.2 与 NumPy 交互
    • 3.3 随机数生成器的兼容性问题
  • 4. 一些🌰
    • 4.1 高性能矩阵运算
    • 4.2 图像处理
    • 4.3 处理大规模数据
  • Ref

1. 引言

在现代软件开发中,Python 以其简洁的语法和丰富的生态系统,成为了数据科学和机器学习领域的首选语言。然而,Python 在执行速度方面并不总是能够满足高性能计算的需求。C++ 则以其卓越的性能和强大的系统级编程能力,常用于性能要求极高的场景。Pybind11 是一个开源工具,旨在简化 C++ 与 Python 之间的交互,使得开发者可以在 Python 中方便地调用 C++ 编写的高性能代码。

1.1 Pybind11 简介

Pybind11 是一个轻量级的头文件库,允许在 C++11 及以上标准下,将 C++ 的函数、类和数据结构绑定到 Python 中。它的设计目标是替代 Boost.Python,但没有后者的编译复杂性和体积。通过 Pybind11,开发者可以:

  • 高效地将 C++ 函数和类暴露给 Python:无需复杂的配置,即可在 Python 中调用 C++ 代码。
  • 支持现代 C++ 特性:兼容 C++11 及以上标准,支持智能指针、模板、枚举等特性。
  • 无缝集成:支持 numpy、Eigen 等常用库的数据类型转换。

1.2 为什么需要 Pybind11

在某些应用场景下,Python 的执行效率可能成为瓶颈,例如:

  1. 计算密集型任务:如大规模矩阵计算、图像处理、机器学习中的核心算法等。
  2. 实时系统:需要对性能有严格要求的系统,如高频交易、实时信号处理等。
  3. 遗留代码复用:已有大量用 C++ 编写的代码库,希望在 Python 项目中直接复用。

使用 Pybind11,可以将性能关键的部分用 C++ 编写,并通过简单的绑定在 Python 中调用,从而兼顾开发效率和运行效率。

2. 使用 Pybind11 进行 C++ 与 Python 交互

2.1 基本用法

Pybind11 的基本用法是通过编写 C++ 代码,将函数或类绑定到 Python 中。以下是一个简单的示例:

// example.cpp
#include <pybind11/pybind11.h>int add(int i, int j) {return i + j;
}PYBIND11_MODULE(example, m) {m.def("add", &add, "A function which adds two numbers");
}

在这个示例中,我们定义了一个简单的 add 函数,并使用 PYBIND11_MODULE 宏将其绑定到 Python 模块 example 中。

2.2 编译与生成共享库

为了在 Python 中使用我们编写的 C++ 模块,需要将其编译为共享库。不同的操作系统下,编译命令略有不同。

2.2.1 在 Linux 下编译

g++ -O3 -Wall -shared -std=c++11 -fPIC $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)

命令解析:

  • g++:GNU C++ 编译器。
  • -O3:最高级别的优化,提升运行效率。
  • -Wall:开启所有警告,帮助发现潜在问题。
  • -shared:生成共享库(.so 文件)。
  • -std=c++11:使用 C++11 标准。
  • -fPIC:生成与位置无关的代码,适用于共享库。
  • $(python3 -m pybind11 --includes):获取 Pybind11 和 Python 的头文件路径。
  • example.cpp:源文件。
  • -o example$(python3-config --extension-suffix):指定输出文件名,$(python3-config --extension-suffix) 获取适当的文件扩展名(如 .so)。

2.2.2 在 macOS 下编译

g++ -O3 -Wall -shared -std=c++11 -undefined dynamic_lookup $(python3 -m pybind11 --includes) example.cpp -o example$(python3-config --extension-suffix)

命令解析:

  • 与 Linux 下基本相同,区别在于:
    • -undefined dynamic_lookup:macOS 特有选项,允许在链接时未定义的符号在运行时解析。

2.2.3 编译选项详解

  • -O3 优化级别

    -O3 是编译器提供的最高级别优化选项,启用所有优化以提升代码运行效率。然而,需要注意的是,过度优化可能会导致编译时间增加,甚至在某些情况下引入不稳定性。

  • -Wall 警告信息

    -Wall 选项开启了编译器的所有常用警告,这有助于在编译阶段发现潜在的代码问题,提高代码质量。

  • -shared 生成共享库

    共享库(Linux 下为 .so 文件,macOS 下为 .dylib.so)可以被多个程序同时使用,节省内存和磁盘空间。在 Python 中,扩展模块通常以共享库的形式存在。

  • -std=c++11 指定标准

    指定使用 C++11 标准,使得我们可以在代码中使用现代 C++ 特性,如智能指针、自动类型推导等。

  • -fPIC 位置无关代码

    生成的位置无关代码可以在内存中任意位置加载,适用于共享库的生成。

  • -undefined dynamic_lookup

    这是 macOS 下的特定选项,允许共享库在编译时不解析未定义的符号,而是在运行时解析。这对于动态语言的扩展模块非常有用。

2.3 在 Python 中使用编译后的模块

编译成功后,会生成一个共享库文件,例如 example.cpython-38-x86_64-linux-gnu.so。在 Python 中,我们可以直接导入并使用:

import exampleresult = example.add(3, 4)
print(result)  # 输出 7

3. 高级用法与注意事项

3.1 绑定类和复杂数据结构

除了函数,Pybind11 也支持将 C++ 类绑定到 Python 中。例如:

#include <pybind11/pybind11.h>class Pet {
public:Pet(const std::string &name) : name(name) {}void setName(const std::string &name_) { name = name_; }const std::string &getName() const { return name; }
private:std::string name;
};PYBIND11_MODULE(example, m) {pybind11::class_<Pet>(m, "Pet").def(pybind11::init<const std::string &>()).def("setName", &Pet::setName).def("getName", &Pet::getName);
}

在 Python 中:

import examplepet = example.Pet("Milo")
print(pet.getName())  # 输出 "Milo"
pet.setName("Otis")
print(pet.getName())  # 输出 "Otis"

3.2 与 NumPy 交互

Pybind11 提供了对 NumPy 数组的支持,可以方便地在 C++ 和 Python 之间传递数组。

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>double sum_array(pybind11::array_t<double> input) {auto buf = input.request();double *ptr = (double *) buf.ptr;size_t size = buf.size;double sum = 0;for (size_t idx = 0; idx < size; idx++)sum += ptr[idx];return sum;
}PYBIND11_MODULE(example, m) {m.def("sum_array", &sum_array, "Sum elements of a NumPy array");
}

在 Python 中:

import example
import numpy as nparr = np.array([1.0, 2.0, 3.0])
result = example.sum_array(arr)
print(result)  # 输出 6.0

3.3 随机数生成器的兼容性问题

在跨语言使用随机数生成器时,需要注意不同语言和库之间的兼容性问题。例如,C++11 提供了 std::mt19937 随机数生成器,而 NumPy 的 np.random.RandomState 则是 Python 中常用的随机数生成器。

问题描述:

  • np.random.RandomStatestd::mt19937 不兼容。这意味着,使用 Pybind11 将 C++ 的随机数生成器暴露给 Python 时,不能直接在 Python 中使用 np.random.RandomState 来设置 C++ 中生成器的状态。

解决方案:

  • 统一随机数生成器:在 C++ 和 Python 中使用相同的随机数生成算法和种子。
  • 通过种子传递:让 Python 将种子传递给 C++,在 C++ 中初始化 std::mt19937
  • 避免共享状态:将随机数的生成完全放在 C++ 或 Python 中,避免在两者之间共享生成器状态。
#include <pybind11/pybind11.h>
#include <random>double random_double(int seed) {std::mt19937 gen(seed);std::uniform_real_distribution<> dis(0.0, 1.0);return dis(gen);
}PYBIND11_MODULE(example, m) {m.def("random_double", &random_double, "Generate a random double");
}

在 Python 中:

import exampleseed = 42
value = example.random_double(seed)
print(value)

通过在 Python 中控制种子,可以在 C++ 中生成可重复的随机数。

4. 一些🌰

为了更深入地理解 Pybind11 的使用,我们将结合实际例子,探讨如何在项目中应用 Pybind11。

4.1 高性能矩阵运算

假设我们需要对大型矩阵进行复杂的运算,而 Python 的性能无法满足需求。我们可以使用 C++ 编写核心计算逻辑,并通过 Pybind11 暴露给 Python。

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>pybind11::array_t<double> matrix_add(pybind11::array_t<double> a, pybind11::array_t<double> b) {auto buf_a = a.request(), buf_b = b.request();if (buf_a.size != buf_b.size)throw std::runtime_error("Input shapes must match");double *ptr_a = (double *) buf_a.ptr;double *ptr_b = (double *) buf_b.ptr;pybind11::array_t<double> result(buf_a.size);auto buf_result = result.request();double *ptr_result = (double *) buf_result.ptr;for (size_t idx = 0; idx < buf_a.size; idx++)ptr_result[idx] = ptr_a[idx] + ptr_b[idx];result.resize({buf_a.shape[0], buf_a.shape[1]});return result;
}PYBIND11_MODULE(example, m) {m.def("matrix_add", &matrix_add, "Add two matrices");
}

在 Python 中:

import example
import numpy as npa = np.ones((1000, 1000))
b = np.ones((1000, 1000))result = example.matrix_add(a, b)
print(result)

通过这种方式,我们可以大幅提升矩阵运算的性能。

4.2 图像处理

在图像处理领域,性能也是关键因素。我们可以利用 C++ 的高性能和 OpenCV 等库,加速图像处理任务。

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>
#include <opencv2/opencv.hpp>pybind11::array_t<uint8_t> convert_to_grayscale(pybind11::array_t<uint8_t> input) {auto buf = input.request();cv::Mat img(buf.shape[0], buf.shape[1], CV_8UC3, (uint8_t *) buf.ptr);cv::Mat gray;cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);pybind11::array_t<uint8_t> result({buf.shape[0], buf.shape[1]}, gray.data);return result;
}PYBIND11_MODULE(example, m) {m.def("convert_to_grayscale", &convert_to_grayscale, "Convert image to grayscale");
}

在 Python 中:

import example
import cv2
import numpy as npimg = cv2.imread('image.jpg')
gray = example.convert_to_grayscale(img)
cv2.imwrite('gray_image.jpg', gray)

4.3 处理大规模数据

在数据科学中,处理大规模数据时,经常需要优化代码性能。以下是一个计算大数组元素平方和的示例:

#include <pybind11/pybind11.h>
#include <pybind11/numpy.h>double sum_of_squares(pybind11::array_t<double> input) {auto buf = input.request();double *ptr = (double *) buf.ptr;size_t size = buf.size;double sum = 0;for (size_t idx = 0; idx < size; idx++)sum += ptr[idx] * ptr[idx];return sum;
}PYBIND11_MODULE(example, m) {m.def("sum_of_squares", &sum_of_squares, "Compute sum of squares");
}

在 Python 中:

import example
import numpy as npdata = np.random.rand(1000000)
result = example.sum_of_squares(data)
print(result)

Ref

[1] https://pybind11.readthedocs.io/en/stable/compiling.html#building-manually

相关文章:

Pybind11的使用

目录 1. 引言1.1 Pybind11 简介1.2 为什么需要 Pybind11 2. 使用 Pybind11 进行 C 与 Python 交互2.1 基本用法2.2 编译与生成共享库2.2.1 在 Linux 下编译2.2.2 在 macOS 下编译2.2.3 编译选项详解 2.3 在 Python 中使用编译后的模块 3. 高级用法与注意事项3.1 绑定类和复杂数…...

鸿蒙-沉浸式pc端失效

咨询描述&#xff1a; 因PC北向窗口涉及沉浸式时&#xff0c;预计发生接口废弃导致不兼容变更&#xff0c;涉及接口setImmersiveModeEnabledState、setWindowLayoutFullSceen 如果应用支持沉浸式&#xff08;窗口全屏且隐藏状态栏&标题栏&Dock栏&#xff09;&#xff0…...

【资料分析】刷题日记1

第一套 第二个是相比2019年的增长率&#xff0c;错找为同比增长率 延申&#xff1a; 当出口和进口相比2019年的增长率相同时&#xff0c;可以用盐水解决 √ 一个假设分配&#xff08;第二次是1.4取1&#xff09;加法对比选项 基期倍数&#xff1a; 求A是B的多少倍&#x…...

nodejs+express+vue教辅课程辅助教学系统 43x2u前后端分离项目

目录 技术栈具体实现截图系统设计思路技术可行性nodejs类核心代码部分展示可行性论证研究方法解决的思路Express框架介绍源码获取/联系我 技术栈 该系统将采用B/S结构模式&#xff0c;开发软件有很多种可以用&#xff0c;本次开发用到的软件是vscode&#xff0c;用到的数据库是…...

96-javahashmap底层原理

HashMap是Java集合框架中的一个重要类&#xff0c;底层是基于哈希表实现的。哈希表是一种数据结构&#xff0c;可以通过哈希函数来提高查找、插入和删除操作的效率。 以下是HashMap底层实现的一些关键点&#xff1a; 哈希算法&#xff1a;HashMap使用哈希算法来计算键的哈希值…...

AI逻辑推理入门

参考数据鲸 (linklearner.com) 1. 跑通baseline 报名 申领大模型API 模型服务灵积-API-KEY管理 (aliyun.com) 跑通代码 在anaconda新建名为“LLM”的环境,并安装好相应包后,在jupyter notebook上运行baseline01.ipynb 2. 赛题解读 一般情况下,拿到一个赛题之后,我们需…...

力扣3014.输入单词需要的最少按键次数I

给你一个字符串 word&#xff0c;由 不同 小写英文字母组成。 电话键盘上的按键与 不同 小写英文字母集合相映射&#xff0c;可以通过按压按键来组成单词。例如&#xff0c;按键 2 对应 ["a","b","c"]&#xff0c;我们需要按一次键来输入 "…...

【Git】远程仓库

本博客的环境是 Ubuntu/Linux 文章目录 集中式与分布式的区别远程仓库新建远程仓库克隆远程仓库向远程仓库推送从远程仓库拉取 配置Git忽略指定文件给命令配置别名 标签管理创建标签操作标签 多人协作本地分支与远程分支连接场景一场景二 集中式与分布式的区别 引荐自关于Git这…...

苹果手机铃声怎么设置自己的歌?3个方法自定义手机铃声

苹果手机内部的手机铃声库只有固定的几首铃声&#xff0c;且都是纯音乐&#xff0c;比较单调&#xff0c;并不是所有用户都喜欢这些铃声。那么&#xff0c;苹果手机铃声怎么设置自己的歌呢&#xff1f;小编这里有3个方法&#xff0c;可以教大家如何将手机铃声设置成自己喜欢的歌…...

828华为云征文|华为Flexus云服务器搭建Cloudreve私人网盘

一、华为云 Flexus X 实例&#xff1a;开启高效云服务新篇&#x1f31f; 在云计算的广阔领域中&#xff0c;资源的灵活配置与卓越性能犹如璀璨星辰般闪耀。华为云 Flexus X 实例恰似一颗最为耀眼的新星&#xff0c;将云服务器技术推向了崭新的高度。 华为云 Flexus X 实例基于…...

【AI学习】AI绘画发展简史

无意中读了一篇发表自2022年的文章&#xff0c;《AI绘画何以突飞猛进? 从历史到技术突破, 一文读懂火爆的AI绘画发展史》&#xff0c;写的比较有意思&#xff0c;科普了好多我原来不知道的历史。 简单提炼一下&#xff0c;做个笔记。 AI绘画重要事件 2012年 Google两位大名…...

使用LangChain创建简单的语言模型应用程序【快速入门指南】

## 引言在这篇文章中&#xff0c;我们将展示如何使用LangChain构建一个简单的语言模型&#xff08;LLM&#xff09;应用程序。这个应用程序的功能是将文本从英语翻译成其他语言。尽管应用程序的逻辑相对简单&#xff0c;但它能够帮助我们学习如何使用LangChain进行更多复杂的功…...

嵌入式人工智能项目及人工智能应用项目——大合集列表查阅

本文的项目合集列表可能更新不及时&#xff08;会及时更新&#xff09;&#xff0c;可查阅实时更新的链接如下。 嵌入式人工智能及人工智能应用项目合集实时更新链接如下&#xff1a; 阿齐嵌入式人工智能及人工智能应用项目合集 (kdocs.cn)https://www.kdocs.cn/l/cc97tuieys4…...

心觉:成功学就像一把刀,有什么作用关键在于使用者(一)

Hi&#xff0c;我是心觉&#xff0c;与你一起玩转潜意识、脑波音乐和吸引力法则&#xff0c;轻松掌控自己的人生&#xff01; 挑战每日一省写作173/1000天 很多人觉得成功学是鸡汤&#xff0c;是没用的&#xff0c;甚至是骗人的 我先保持中立&#xff0c;不知道对不对 我们先…...

GAMES101(10节,几何)

Geometry implicit隐式几何表示&#xff1a; 函数f(x,y,z)&#xff1a; 根据函数fn描述几何&#xff0c;遍历所有空间内 的点&#xff0c;如果带入xyz到函数f(x,y,z)结果0那就绘制这个点 如果xyz求值结果>0表示在几何外&#xff0c;0在表面,<0在几何内 构造几何csg(…...

Android 中音频焦点的使用场景及示例

Android 中音频焦点的使用场景及代码示例 一、音频焦点简介 在 Android 系统中&#xff0c;音频焦点&#xff08;Audio Focus&#xff09;是一种机制&#xff0c;用于管理多个应用程序同时播放音频时的冲突。当一个应用程序请求音频焦点并获得它时&#xff0c;其他应用程序在…...

2. JDBC驱动是什么?如何在Java项目中配置MySQL的JDBC驱动?

JDBC驱动 是一种软件组件&#xff0c;它使Java应用程序能够与数据库进行交互。JDBC驱动是JDBC API的实现&#xff0c;负责将Java程序中的标准JDBC方法调用转化为数据库特定的操作。每个数据库&#xff08;如MySQL、PostgreSQL、Oracle等&#xff09;都有对应的JDBC驱动程序&…...

Nginx 跨域 + 无法设置 Cookie 解决办法

今天来分享一下关于项目部署上线时怎么解决跨域问题!!! 首先感谢一下大佬的方法,才让这个困扰我很久的问题得以解决!!! 这也是我请教大佬才解决的问题,大佬和我说,这是他耗费两周才解决的问题,我这也是属于前人栽树后人乘凉了,嘿嘿嘿!!! 前端问题 前端没有携带 cookie 导致后端…...

北森笔试测评之言语理解到底难不难

前篇笔记我提到过&#xff0c;言语理解是最难的&#xff0c;有同学质疑了。言语我都会做呀&#xff0c;甚至有的可以搜到&#xff0c;而图标和图形我有的不会。这里需要指出&#xff0c;会做不等于作对&#xff0c;可以回顾到高中甚至初中的时候&#xff0c;感觉做的好的一般都…...

Ubuntu下beanstalkd无法绑定局域网IP地址以及消息队列beanstalkd上的error: JOB_TOO_BIG的解决

一、ubuntu下beanstalkd无法绑定局域网IP地址 今天因为业务需要&#xff0c;我把之前安装的beanstalkd所绑定的IP地址由127.0.0.1改成局域网IP地址&#xff0c;但是怪了&#xff0c;显示beanstalkd已经启动&#xff0c;查看端口监控也显示IP地址变了&#xff0c;但是使用telnet…...

网络原理(3)—— 应用层、传输层(TCP)

1. 应用层 日常开发中最常用到的一层&#xff0c;主要涉及到两种情况&#xff1a; 1) 使用现成的应用层协议 2) 自己定义应用层协议 1.1 自定义应用层协议的流程 1. 明确前后端交互过程中需要传递哪些信息 实例&#xff1a;开发一个外卖软件 打开软件&#xff0c;首先需要展…...

Flutter - Win32程序是如何执行main函数

Win32程序的主体结构 int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,_In_ wchar_t *command_line, _In_ int show_command) {// Attach to console when present (e.g., flutter run) or create a// new console when running with a debugger.if …...

linux-系统管理与监控-日志管理

Linux 系统管理与监控&#xff1a;日志管理 1. 日志管理概述 日志文件是系统在运行过程中记录的各种信息&#xff0c;它们是系统管理员排查问题、监控系统健康状况的重要工具。在 Linux 系统中&#xff0c;日志涵盖了系统事件、内核信息、用户操作、软件服务和应用程序等内容…...

VulhubDC-4靶机详解

项目地址 https://download.vulnhub.com/dc/DC-4.zip实验过程 将下载好的靶机导入到VMware中&#xff0c;设置网络模式为NAT模式&#xff0c;然后开启靶机虚拟机 使用nmap进行主机发现&#xff0c;获取靶机IP地址 nmap 192.168.47.1-254根据对比可知DC-4的一个ip地址为192.1…...

[数据集][目标检测]烟叶病害检测数据集VOC+YOLO格式612张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;612 标注数量(xml文件个数)&#xff1a;612 标注数量(txt文件个数)&#xff1a;612 标注类别…...

Sapiens——人类视觉大模型的基础

引言 大规模预训练以及随后针对特定任务的语言建模微调取得了显著成功&#xff0c;已将这种方法确立为标准做法。同样&#xff0c; 计算机视觉方法正逐步采用大规模数据进行预训练。LAION5B、Instagram-3.5B、JFT-300M、LVD142M、Visual Genome 和 YFCC100M 等大型数据集的出现…...

《深度学习》【项目】 OpenCV 身份证号识别

目录 一、项目实施 1、自定义函数 2、定位模版图像中的数字 1&#xff09;模版图二值化处理 运行结果&#xff1a; 2&#xff09;展示所有数字 运行结果&#xff1a; 3、识别身份证号 1&#xff09;灰度图、二值化图展示 运行结果 2&#xff09;定位身份证号每一个数…...

机器学习实战—天猫用户重复购买预测

目录 背景 数据集 用户画像数据 用户行为日志数据 训练数据 测试数据 提交数据 其它数据 数据探索 导入依赖库 读取数据 查看数据信息 缺失值分析 数据分布 复购因素分析 特征工程 模型训练 模型验证 背景 商家有时会在特定日期,例如节礼日(Boxing-day),黑…...

一款rust语言AI神器cursor在ubuntu环境下的安装启动教程

虽然cursor目前只支持英文但是它强大的代码联想能力以及问答能力&#xff0c;可以高效的提高编码效率。 如下步骤所有的前提是你的ubuntu上面已经安装了vscode以及其必须的extensions。 1 下载 到官网https://www.cursor.com下载指定版本的软件。 下载到本地以后会生成如下软…...

【C#生态园】发现C#中的数据科学魔法:6款不可错过的库详解

探索C#中的数据科学与机器学习&#xff1a;6个强大库解析 前言 在数据科学和机器学习领域&#xff0c;Python一直占据着主导地位&#xff0c;然而对于习惯使用C#编程语言的开发人员来说&#xff0c;寻找适用于C#的数据科学库一直是一个挑战。本文将介绍几个流行的用于C#的数据…...