当前位置: 首页 > 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…...

如何用Video2X实现视频画质智能增强?零基础入门到精通指南

如何用Video2X实现视频画质智能增强&#xff1f;零基础入门到精通指南 【免费下载链接】video2x A lossless video/GIF/image upscaler achieved with waifu2x, Anime4K, SRMD and RealSR. Started in Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trend…...

芯片验证工程师必备:SVA断言中的assert/cover/assume核心区别与典型误用案例

芯片验证工程师必备&#xff1a;SVA断言中的assert/cover/assume核心区别与典型误用案例 在芯片验证领域&#xff0c;SystemVerilog Assertion&#xff08;SVA&#xff09;是验证工程师不可或缺的利器。对于1-3年经验的验证工程师而言&#xff0c;深入理解assert、cover和assum…...

别再手动填Excel了!用Java+Spire.XLS 15.6.3实现批量报表自动化(附完整源码)

Java报表自动化革命&#xff1a;Spire.XLS实战指南与生产力跃迁 凌晨三点的办公室&#xff0c;最后一份月度销售报表终于核对完毕。这样的场景是否似曾相识&#xff1f;据统计&#xff0c;全球超过70%的企业级数据仍通过Excel流转&#xff0c;而其中近40%的时间消耗在机械化的…...

开箱即用:BAAI/bge-m3镜像,一键启动语义相似度分析WebUI

开箱即用&#xff1a;BAAI/bge-m3镜像&#xff0c;一键启动语义相似度分析WebUI 1. 快速上手&#xff1a;从零到一的十分钟体验 你是不是也遇到过这样的场景&#xff1f;手头有两段文字&#xff0c;想知道它们说的是不是一回事&#xff0c;或者想快速验证一下自己构建的AI知识…...

Qwen2.5-7B-Instruct入门指南:7B模型对输入token长度的鲁棒性压力测试

Qwen2.5-7B-Instruct入门指南&#xff1a;7B模型对输入token长度的鲁棒性压力测试 1. 项目概述 Qwen2.5-7B-Instruct是阿里通义千问系列的旗舰级大模型&#xff0c;相比1.5B和3B轻量版本&#xff0c;7B参数规模带来了质的飞跃。这个模型在逻辑推理、长文本创作、复杂代码编写…...

Path of Building:流放之路构筑规划的精准导航工具

Path of Building&#xff1a;流放之路构筑规划的精准导航工具 【免费下载链接】PathOfBuilding Offline build planner for Path of Exile. 项目地址: https://gitcode.com/gh_mirrors/pat/PathOfBuilding 在《流放之路》复杂多变的角色构建世界中&#xff0c;Path of …...

音频处理必备:5分钟搞懂IIR和FIR滤波器的区别与应用场景

音频处理必备&#xff1a;5分钟搞懂IIR和FIR滤波器的区别与应用场景 在音乐制作和音频工程领域&#xff0c;滤波器是塑造声音的核心工具之一。无论是调整均衡、消除噪声还是创造特殊音效&#xff0c;都离不开对IIR和FIR这两类滤波器的深入理解。许多刚入门的音频工程师常常困惑…...

提升数据抓取效率:用快马AI生成openclaw命令自动化脚本模板

最近在做一个数据抓取项目时&#xff0c;发现手动写openclaw命令实在太费时间了。每次都要重复写类似的fetch和parse命令&#xff0c;还要处理各种异常情况。后来发现用InsCode(快马)平台可以快速生成自动化脚本模板&#xff0c;效率提升了好几倍。今天就把这个经验分享给大家。…...

Ubuntu系统身份标识重塑:主机名与用户名的安全变更指南

1. 为什么要修改Ubuntu的主机名和用户名&#xff1f; 很多朋友第一次接触Ubuntu系统时&#xff0c;安装过程中随手设置的主机名和用户名&#xff0c;可能没想到后续会带来这么多麻烦。我遇到过不少这样的情况&#xff1a;公司服务器的主机名还是默认的"ubuntu"&#…...

MinerU智能文档理解服务新手教程:5分钟搭建PDF解析系统

MinerU智能文档理解服务新手教程&#xff1a;5分钟搭建PDF解析系统 1. 引言&#xff1a;文档智能解析的实用价值 每天我们都会遇到各种PDF文档——合同、报告、论文、发票&#xff0c;手动提取内容不仅耗时还容易出错。MinerU智能文档理解服务正是为解决这个问题而设计&#…...