将 Python 程序转换为 C/C++ 代码?

Posted

技术标签:

【中文标题】将 Python 程序转换为 C/C++ 代码?【英文标题】:Convert Python program to C/C++ code? 【发布时间】:2011-06-06 17:17:27 【问题描述】:

是否可以将 Python 程序转换为 C/C++?

我需要实现几个算法,但我不确定性能差距是否足以证明我在 C/C++ 中所经历的所有痛苦(我不擅长)。我考虑过编写一个简单的算法,并将其与这种转换后的解决方案进行基准测试。如果仅此一项就比 Python 版本快得多,那么我别无选择,只能在 C/C++ 中进行。

【问题讨论】:

尽管 Python 在基准测试中损失了很多,但请记住,如果在 Python 中计算在几秒钟内完成,那么 50 倍或 100 倍的减速仍然可以忽略不计,即使你做了很多 I /O 或有一个可怕的算法。而不是问“Python 慢了多少?”你应该问“Python 够快吗?” (老实说,最有可能的是)-这也比基准测试或在这里询问要快。 在 python 中实现一个算法是非常快速和直接的......你只需要这样做,然后检查它是否足够快。大多数时候,您可以使用不同的数据结构(字典/集合而不是列表...)或不同的操作来优化算法以更快地运行。无论如何,优化应该发生在您已经实现了算法的初稿并对其进行基准测试/分析之后。 @delnan:就我而言,这完全与计算时间有关。如果 C 变体需要减少 x 小时,那么我会花时间让算法运行更长时间/再次运行。我只是想(粗略地)找出 Python 会慢多少——如果只是几个小时,我当然不会使用我不习惯的语言(你可能会破坏实现不良问题的最佳解决方案: P)。 @delnan 说的对,Python 可能对很多事情都足够快。即使速度较慢,开发、维护和未来增强的难易程度也是需要考虑的重要因素。 “x 小时”?这是多大?您是否对实现进行了基准测试?你有测量值吗?您是否对实施进行了概要分析?还是您试图过早地优化解决方案? 【参考方案1】:

如果 C 变体需要的时间减少 x 小时,那么我会花时间让算法运行更长/再次

“投资”在这里用词不当。

    在 Python 中构建一个有效的实现。你会在完成 C 版本之前完成这个。

    使用 Python 分析器测量性能。解决您发现的任何问题。根据需要更改数据结构和算法以真正正确地执行此操作。你将在完成 C 的第一个版本之前完成这个。

    如果还是太慢,请手动将精心设计和精心构建的 Python 翻译成 C。

    由于事后诸葛亮的工作方式,从现有 Python(使用现有单元测试和现有分析数据)执行第二个版本仍然比尝试从头开始编写 C 代码更快。

这句话很重要。

Thompson 对首次望远镜制造商的规则 做一个四英寸的镜子,然后是一个六英寸的镜子,比做一个六英寸的镜子要快。

比尔·麦基南 王学院

【讨论】:

不管分数有多高,我看不出这如何回答这个问题。 @Audrius Meskauskas,它没有,它消除了它,使问题的前提变得不必要。换句话说,它解释了如何做比所要求的更好的事情,而不是被要求的。 就我而言,我会单独为最后的报价投票。当外推到用 C 语言编程时,这非常有见地。我正在用 C 语言实现 fast_malloc()。我在一个我认为需要几天时间的项目上进行了 4 周。我的大部分时间都花在了代码的支持结构上,而不是代码本身。如果建造一个棚子是目标,我的大部分精力都花在了制造钉子、锤子、锯子和制造油漆的化学物质上,这样我就可以制作用来混合油漆的罐子和油漆也粘,然后是油漆。【参考方案2】:

是的。看Cython。它就是这样做的:将 Python 转换为 C 以加快速度。

【讨论】:

当然,除非您添加一堆 cdef 声明并因此引入静态类型(否则您只能处理不透明的 PyObject * 东西),否则不会为您节省任何东西。而且它永远不会像普通 C 一样快,因为它通常与 Python 交互(100% 或更多?仅适用于大多数时间根本不与 Python 交互的普通数字代码!)。但除此之外,是的,它可以让你获得相当大的加速。 @delnan:事实上,它确实为您节省了一些东西。大多数纯 Python 代码在编译后会更快。但是,是的,使用 cdefs 和静态类型,您真正开始看到差异。在所有使用 Python 中的 C 的情况下,您都可以获得与 Python 的接口。【参考方案3】:

Shed Skin 是“一个(受限的)Python-to-C++ 编译器”。

【讨论】:

+1 Shed Skin 的一个优点是类型推断:如果可以从程序流中猜测变量类型,则可以避免动态类型检查。这通常会导致更短的 C++ 代码实际上可以读取并编译为更快的程序。 还有Python → 11l → C++ transpiler,它也是一个受限的Python to C++编译器,但是它支持一些Python特性,Shed Skin不支持(例如嵌套函数/闭包)。【参考方案4】:

刚刚在黑客新闻中看到this 新工具。

从他们的页面 - “Nuitka 是 Python 解释器的一个很好的替代品,它编译 CPython 2.6、2.7、3.2 和 3.3 提供的每个结构。它将 Python 转换为 C++ 程序,然后使用“libpython”在与 CPython 一样,以一种非常兼容的方式。”

【讨论】:

这个项目比其他类似选项成熟得多。有趣的是,它在 OSX 上创建了带有 .exe 扩展名的二进制文件,即使它是一个完全正常的 OSX Mach-O 可执行文件。看起来它可能是pyinstallerpy2exepy2app 等的一个很好的替代品。--recurse-*** 标志对于正确设置很重要。 Nuitka 很棒,但是创建的 C/C++ 代码使用绑定到 CPython-C-code-implementation 的 PyObject。它不会产生惯用的 C 代码。【参考方案5】:

我知道这是一个较旧的帖子,但我想提供我认为有用的信息。

我个人使用 PyPy,它很容易使用 pip 安装。我可以互换使用 Python/PyPy 解释器,您根本不需要更改代码,而且我发现它比标准 Python 解释器(Python 2x 或 3x)快大约 40 倍。我使用 pyCharm Community Edition 来管理我的代码,我喜欢它。

我喜欢用 python 编写代码,因为我认为它可以让你更多地专注于任务而不是语言,这对我来说是一个巨大的优势。如果你需要它更快,你总是可以编译为 Windows、Linux 或 Mac 的二进制文件(不是直接的,但可以使用其他工具)。根据我的经验,我在编译时比 PyPy 获得了大约 3.5 倍的加速,这意味着比 python 快 140 倍。 PyPy 可用于 Python 3x 和 2x 代码,同样,如果您使用像 PyCharm 这样的 IDE,您可以非常轻松地在 PyPy、Cython 和 Python 之间进行互换(尽管需要一些初始学习和设置)。

有些人可能会在这个问题上与我争论,但我发现 PyPy 比 Cython 快。但它们都是不错的选择。

编辑:我想对编译做一个简短的说明:当你编译时,生成的二进制文件比你的 python 脚本要大得多,因为它会将所有依赖项构建到其中等等。但是然后您将获得一些明显的好处:速度!,现在该应用程序可以在没有 Python 或库的任何机器上运行(取决于您编译的操作系统,如果不是全部。哈哈),它还会混淆您的代码,并且在技术上“生产”准备好(到一个程度)。一些编译器还生成 C 代码,我没有真正看过或看到它是否有用或只是胡言乱语。祝你好运。

希望对您有所帮助。

【讨论】:

我知道这是一个较旧的评论,但谢谢! 没问题,我很高兴它有用。 你用什么软件从 PyPy 解释编译? 不是专门的 PyPy,只是 .py 脚本。 Nuitka 如果您想要“C/C++ 可执行文件或 C/C++ 源代码”,如果您只想要一个可执行文件(更简单),则使用 PyInstaller。还有 py2exe,但我的成功率较低,尽管我确信情况有所改善。 PyInstaller 也是跨平台的,不仅适用于 Windows 可执行文件(适用于 Linux 和 Mac)。 Nuitka 是独一无二的,因为我认为它是唯一可以为您提供可用源代码的“编译器”,理论上您可以进一步优化。还有一些其他的,例如 bbFreeze、cx_Freeze 和 py2app,但我还没有尝试过。祝你好运! 我还发现 PyPy 比 Cython 运行得更快。在一项测试中,我实际上发现 PyPy 的速度与程序的 C++ 版本相同(插入排序)。【参考方案6】:

除了 Shed Skin 之外,另一个选项 - 转换为 C++ - 是Pythran。

引用 Micha Gorelick 和 Ian Ozsvald 的高性能 Python

Pythran 是 Python 到 C++ 的编译器,适用于 Python 的一个子集, 包括部分numpy 支持。它的行为有点像 Numba 和 Cython——你注释一个函数的参数,然后它接管 进一步的类型注释和代码专业化。它需要 矢量化可能性和基于 OpenMP 的优势 并行化的可能性。它仅使用 Python 2.7 运行。

Pythran 的一个非常有趣的特性是它会尝试 自动发现并行化机会(例如,如果您 使用map),并将其转换为并行代码,而不需要额外的 你的努力。您还可以使用pragma omp > 指令指定并行部分;在这方面,感觉和 Cython 的很像 OpenMP 支持。

在幕后,Pythran 将采用普通 Python 和 numpy 代码 并尝试积极地将它们编译成非常快的 C++——甚至 比 Cython 的结果更快。

你应该注意这个项目是年轻的,你可能会遇到 错误;您还应该注意,开发团队非常友好 并且往往会在几个小时内修复错误。

【讨论】:

请注意,“在 0.9.5(包括)之前,Pythran 一直支持 Python 3 和 Python 2.7。它现在只支持 Python 3。”【参考方案7】:

http://code.google.com/p/py2c/ 看起来很有可能——他们还在他们的网站上提到:Cython、Shedskin 和 RPython,并确认他们正在将 Python 代码转换为纯 C/C++,这比充斥着 Python API 调用的 C/C++ 快得多。注意:我还没有尝试过,但我会..

【讨论】:

看来Py2C还是一个未完成的项目。它已经几年没有更新了,所以它可能已经失效了。 @ashley 还是很有用的,谢谢 - 它可以是一个很好的替代品。解决方案,感谢您发布此内容。【参考方案8】:

我意识到缺少一个全新解决方案的答案。如果代码中使用了 Numpy,我建议尝试 Pythran:

http://pythran.readthedocs.io/

对于我尝试过的函数,Pythran 给出了非常好的结果。生成的函数与编写良好的 Fortran 代码一样快(或仅稍慢一些),并且比(相当优化的)Cython 解决方案快一点。

与 Cython 相比的优势在于,您只需在针对 Numpy 优化的 Python 函数上使用 Pythran,这意味着您不必扩展循环并为循环中的所有变量添加类型。 Pythran 会花时间分析代码,以便了解 numpy.ndarray 上的操作。

与 Numba 或其他基于即时编译的项目相比,这也是一个巨大的优势(据我所知),您必须扩展循环才能真正高效。然后只有使用 CPython 和 Numpy 的循环代码变得非常低效......

Pythran 的一个缺点:没有类!但是由于只需要编译真正需要优化的函数,所以也不是很烦人。

另一点:Pythran 很好地(并且非常容易地)支持 OpenMP 并行性。但我认为不支持 mpi4py...

【讨论】:

以上是关于将 Python 程序转换为 C/C++ 代码?的主要内容,如果未能解决你的问题,请参考以下文章

将 C/C++ 向量快速转换为 Numpy 数组

C ++会首先转换为程序集吗?

C#环境如何将一个字符串转换为代码执行?

python怎么将数组转换为矩阵

[转] python关于ctypes使用char指针与bytes相互转换的问题

如何编程实现视频转码? 用C/C++实现将MPEG4标准的视频转化为H.264标准的视频