为什么 cython 嵌入插件在 python 解释器中比 rust-c 接口版本具有更高的性能?

2024-01-01

我想问一些关于python解释器的底层原理的问题,因为我自己搜索的过程中并没有得到太多有用的信息。

我最近一直在使用 rust 编写 python 插件,这为 python 的 cpu 密集型任务提供了显着的加速,并且与 c 相比,编写速度也更快。不过它有一个缺点就是,相对于旧的使用cython加速的方案,rust(我使用的是pyo3)的调用开销似乎比c(我使用的是cython)的调用开销更大,

例如,我们在这里得到一个空的 python 函数:

def empty_function():
    return 0

在Python中通过for循环调用它一百万次并计算时间,这样我们就可以发现每次调用大约需要70纳秒(在我的电脑中)。

如果我们将其编译为 cython 插件,具有相同的源代码:

# test.pyx
cpdef unsigned int empty_function():
    return 0

执行时间将减少至 40 纳秒。这意味着我们可以使用 cython 进行一些细粒度的嵌入,并且我们可以期望它总是比原生 python 执行得更快。

然而,当谈到 Rust 时,(老实说,我现在更喜欢使用 rust 进行插件开发而不是 cython,因为不需要在语法上做一些奇怪的黑客攻击),调用时间将增加到 140 纳秒,几乎是原生蟒蛇。源码如下:

use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
fn empty_function() -> usize {
    0
}

#[pymodule]
fn testlib(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_function(wrap_pyfunction!(empty_function, m)?)?;
    Ok(())
}

这意味着rust不适合对python进行细粒度的嵌入式替换。如果有一个任务的调用时间很少,并且每次调用的时间都比较长,那么使用 Rust 就完美了。然而,如果有一个任务会在代码中被大量调用,那么它似乎不适合 rust ,因为类型转换的开销将占用大部分加速时间。

我想知道这个问题是否可以解决,更重要的是,我想知道造成这种差异的根本原因。在它们之间调用时,cpython解释器是否有某种区别,就像调用c插件时cpython和pypy之间的区别一样?我在哪里可以获得更多信息?谢谢。

===

Update:

抱歉大家,我没想到我的问题会含糊不清,毕竟这三个问题的源代码都已经给出了,并且使用 timeit 来测试函数运行时几乎是 python 开发中的惯例。

我的测试代码与注释中 @Jmb 的代码几乎完全相同,但我使用的有一些细微的差别python setup.py build_ext --inplace构建方式而不是裸 gcc,但这应该没有任何区别。不管怎样,谢谢补充。


正如评论中所建议的,这是一个自我回答。

由于评论部分的讨论没有得出明确的结论,我去 pyo3 的 repo 中提出了一个问题,并得到了其主要维护者的回应。

总之,结论是pyo3或cython编译的插件在cpython调用时没有本质区别。目前的速度差异来自于优化深度的不同。

这是问题的链接:https://github.com/PyO3/pyo3/issues/1470 https://github.com/PyO3/pyo3/issues/1470

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 cython 嵌入插件在 python 解释器中比 rust-c 接口版本具有更高的性能? 的相关文章

随机推荐

  • Golang 模板“减号”功能

    我知道在go我可以调用名为的模板函数add对于像这样的表达1 1 但是如何为表达式命名函数2 1 没有add默认包含的功能 但是 您可以轻松地自己编写此类函数 例如 tmpl template Must template New Funcs
  • 为什么 C++ 标准文件流没有更严格地遵循 RAII 约定?

    为什么 C 标准库使用流open close 语义与对象生命周期分离 从技术上讲 关闭销毁可能仍会生成类 RAII 但获取 释放独立性会在范围内留下漏洞 其中句柄可以指向任何内容 但仍需要运行时检查来捕获 为什么库设计者选择他们的方法而不是
  • Django 教程:运行服务器错误

    我正在遵循 django 教程 但我立即在第 1 部分中遇到了问题 运行 python manage py runserver 后 我在浏览器中输入 URL 并收到错误 ImproperlyConfigured Module django
  • 如何使用 jQuery 查找特定类型(表)的最后一个子项?

    假设我有以下结构 div table tbody tr td div table tbody tr td div table Last table here table div td tr tbody table div td tr tbo
  • 使用 Android NDK 中的系统函数在 Android 嵌入式设备上运行 Shell 脚本文件

    All 这里我想通过android NDK中的系统调用运行 sh文件 我能跑cp rm通过系统调用命令 但 sh 命令无法通过系统调用运行 我还在 android 上安装 busybox 我使用下面的代码 我设置了所有权限test sh C
  • Swift 中根据 String 计算出 UILabel 的大小

    我正在尝试根据不同的字符串长度计算 UILabel 的高度 func calculateContentHeight gt CGFloat var maxLabelSize CGSize CGSizeMake frame size width
  • AWS Textract - GetDocumentAnalysisRequest 仅返回文档第一页的正确结果

    我编写了使用 Amazon Textract 从 pdf 中提取表和名称值对的代码 我按照这个例子 https docs aws amazon com texttract latest dg async analyzing with sqs
  • ES6 的参数名称?

    我定义了一个函数 例如 function call api url callback query body 我期望有一种可以提供正文并跳过查询的语法 call api api clients new function x console l
  • 为什么 swift 不警告这个不可发送的全局传递到不同的任务?

    考虑以下代码 class Cat var name Tom class Globals var cat Cat let glob Globals func one Task glob cat name Max Expected Warnin
  • ocamlbuild;建筑顶层

    已成功使用子目录重新组织了我的 ocamlbuild 项目 https stackoverflow com questions 2209532 properly compiling modules in subfolders ocamlbu
  • 在 GAE 中实施独特的约束

    我正在尝试 Google App Engine Java 但是缺乏独特的约束使事情变得困难 我已经通过这篇文章 https stackoverflow com questions 2626978 unique constraint at d
  • 隐藏 Jinja2 模板中无法访问的链接

    我们正在工作中使用 Flask Jinja2 编写一个 Web 应用程序 该应用程序具有注册用户 可以根据其角色访问某些页面 为了在服务器端实现这一点 我们只需使用装饰页面 app route action1 security requir
  • 如何根据 Unix 时间戳计算本地时间

    如果unix时间戳在世界各地都是相同的 我如何才能获得本地时间 或者是根据不同的时区时间戳不同 也就是说 我在美国 UTC 1970 的当前秒数是 5 000 但如果我在亚洲并检查时间戳 那么它将是 4 000 秒 世界上每个国家的 UTC
  • 使用由单个安装程序安装的 SQLite 的 Java 桌面应用程序

    我是与数据库交互的 Java 桌面应用程序编程的初学者 我的目标是制作一个简单的java应用程序 它使用数据库在本地存储数据 经过一番谷歌搜索后 我发现 SQLite Derby 可以满足我的需求 我用谷歌搜索了 SQLite 和 Derb
  • App 类中的静态上下文 - 内存泄漏

    为了能够在应用程序中的任何位置获取应用程序上下文 我创建了这样的 App 类 public class App extends Application private static Context mContext public stati
  • 带 if 语句的 Postgresql 函数

    我怎样才能使这个伪代码在 Postgresql 中工作 create or replace function getf arg character varying 255 returns int as if arg a then retur
  • Python 网页抓取被阻止

    我想抓取德国房地产网站 immobilienscout24 de 的网页 我想下载给定 URL 的 HTML 然后离线使用该 HTML 它不适合商业用途或出版 我也不打算向该网站发送垃圾邮件 它只是用于编码练习 我想编写一个 python
  • 核心数据谓词日期比较

    我试图获取与用户 selectedDate 匹配的实体中的所有对象 它是 NSDate 核心数据代码很好 但我的谓词一直返回 0 结果 数据库中的日期与用户选择的日期相同 应如何使用谓词将 selectedDate 与实体中的日期进行比较
  • 使用 VS 2005 C# 将 Excel 转换为 Oracle 数据库

    我想构建一个实用程序 可以将 Excel 工作表 列是固定的 但工作表可以是任意数量 中的数据导入到 Oracle 数据库 你能建议我应该如何 读取Excel表格 n张 最好的方法 验证数据 批量插入数据库 我关心的是这里的表现 每张纸可以
  • 为什么 cython 嵌入插件在 python 解释器中比 rust-c 接口版本具有更高的性能?

    我想问一些关于python解释器的底层原理的问题 因为我自己搜索的过程中并没有得到太多有用的信息 我最近一直在使用 rust 编写 python 插件 这为 python 的 cpu 密集型任务提供了显着的加速 并且与 c 相比 编写速度也