【问题标题】:In Python, why is a module implemented in C faster than a pure Python module, and how do I write one?在 Python 中,为什么用 C 语言实现的模块比纯 Python 模块更快,我该如何编写?
【发布时间】:2011-01-06 14:46:46
【问题描述】:

python 文档指出,cPickle 比 Pickle 快的原因是前者是用 C 实现的。这到底是什么意思?

我正在用 Python 制作一个高级数学模块,一些计算需要花费大量时间。这是否意味着如果我的程序是用 C 语言实现的,它可以变得更快?

我希望从其他 Python 程序中导入这个模块,就像我可以导入 cPickle 一样。

您能解释一下如何在 C 中实现 Python 模块吗?

【问题讨论】:

    标签: python c python-c-api


    【解决方案1】:

    您可以编写快速的 C 代码,然后在您的 python 脚本中使用它,这样您的程序将运行得更快。[1] http://docs.python.org/extending/index.html#extending-index

    一个例子是 Numpy,用 C 语言编写 (https://numpy.org/)

    典型的用途是在 C 中实现瓶颈(或者使用用 C 编写的库,当然;)),由于它的速度,其余代码使用 python

    [1] 顺便说一下,这就是 cPickle 比 pickle 快的原因

    编辑:

    看看 Pyrex:http://www.cosc.canterbury.ac.nz/greg.ewing/python/Pyrex/version/Doc/About.html

    'Pyrex 是一种特殊的语言 专为编写 Python 扩展而设计 模块。它旨在桥接 好,高水平之间的差距, 易于使用的 Python 世界和 杂乱无章的低级 C 世界。'

    这不是“官方”方式,但它可能有用

    【讨论】:

    • +1 您应该将核心计算的纯 C 实现与使用 Numpy 进行繁重工作的 Python 实现进行基准测试。 Numpy 实施很有可能具有竞争力。
    • +1 表示 Numpy。很有可能,如果 Numpy 做你想做的事,它会比你写的任何东西都快,而无需投入大量时间优化代码。
    【解决方案2】:

    如前所述,numpy 非常适合向量计算。 (可能会更好,但评论说它比你不用实际工作就可以写的任何东西都要好。)

    不过,并非所有内容都可以轻松矢量化,因此,如果您确实有带有大量函数调用的紧密内部循环(比如一个高度递归的算法),您仍然有几个选择:可能最受欢迎的是 Cython,它允许您在一种带注释的 Python 中编写模块和函数,并在需要时获得类似 C 的速度。

    或者,也许您的时间都被用于计算特征值或反转矩阵或评估特殊函数或划分非常大的整数的库调用所支配 - 顺便说一下,如果您想要的话,Sage 项目中的许多都可以很好地处理重新做比纯粹的运算更具数学性——在这种情况下,花在 Python 上的时间甚至可能无关紧要。这完全取决于您正在做的数字类型的详细信息。

    【讨论】:

      【解决方案3】:

      当你在 python 中编写一个函数时,一个新的函数对象被创建,函数代码被解析和字节编译[并保存在“func_code”属性中],所以当你调用那个函数时,解释器读取它的字节码并执行它.

      如果您在 C 中编写相同的函数,遵循 C/Python API 使其在 python 中可用,解释器将创建函数对象,但该函数没有字节码。 当解释器找到对该函数的调用时,它会调用真正的 C 函数,因此它以“机器”速度而不是“python 机器”速度执行。

      您可以验证这个用 C 编写的检查函数:

      >>> map.func_code
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      AttributeError: 'builtin_function_or_method' object has no attribute 'func_code'
      >>> def mymap():pass
      ... 
      >>> mymap.func_code
      <code object mymap at 0xcfb5b0, file "<stdin>", line 1>
      

      要了解如何编写用于 python 的 C 代码,请遵循官方网站中的指南。

      无论如何,如果你只是简单地进行 N 维数组计算,numpy 应该就足够了。

      【讨论】:

      • 我正在做一些不同的事情,我在网络上的任何地方都找不到,无论如何这有帮助,谢谢!
      【解决方案4】:

      除了前面提到的 Pyrex/Cython,您还有其他选择:

      Shed Skin:将 Python 的(受限子集)翻译成 C++。可以自动为您生成扩展名。您将创建一个扩展来执行此操作(假设是 Linux):

      wget http://shedskin.googlecode.com/files/shedskin-0.7.tgz
      tar -xzf shedskin-0.7.tgz
      # On your code folder:
      PYTHONPATH=/path/to/shedskin-0.7 python shedskin -e yourmodule.py
      # The above generates a Makefile and a yourmodule.h/.cpp pair
      make
      # Now you can "import yourmodule" from Python and check it's from the .so by "print yourmodule.__file__
      

      PyPy:更快的 Python,带有 JIT 编译器。你可以简单地在它上面运行你的代码而不是 CPython。目前仅支持 Python 2.5,即将支持 2.7。可以极大地加速数学繁重的代码。安装和运行它(假设 Linux 32 位):

      wget http://pypy.org/download/pypy-1.4.1-linux.tar.bz2
      tar -xjf pypy-1.4.1-linux.tar.bz2
      sudo ln -s /path/to/pypy-1.4.1-linux/bin/pypy /usr/local/bin
      # Then, instead of "python yourprogram.py" you'll just run "pypy yourprogram.py"
      

      Weave:允许你write C inline,编译它。

      编辑:如果您希望我们为您运行这些工具并进行基准测试,只需发布​​您的代码;)

      【讨论】:

        猜你喜欢
        • 2016-09-12
        • 2013-05-06
        • 1970-01-01
        • 2021-09-09
        • 2022-12-09
        • 2012-03-11
        • 1970-01-01
        • 1970-01-01
        • 2020-08-26
        相关资源
        最近更新 更多