Cython 程序(打印 Hello world)比纯 Python 慢得多

Cython program (print Hello world) much slower than pure Python

我是 Cython 的新手。我写了一个超级简单的测试程序来获得 Cython 的好处。然而,我的纯 python 速度要快得多。难道我做错了什么? test.py:

import timeit
imp = '''
import pyximport; pyximport.install()
from hello_cy import hello_c
from hello_py import hello_p
'''

code_py = '''
hello_p()
'''

code_cy = '''
hello_c()
'''

print(timeit.timeit(stmt=code_py, setup=imp))
print(timeit.timeit(stmt=code_cy, setup=imp))

hello_py.py:

def hello_p():
    print('Hello World')

hello_cy.pyx:

from libc.stdio cimport printf

cpdef void hello_c():
    cdef char * hello_world = 'hello from C world'
    printf(hello_world)

hello_py时间耗时14.697s

hello_cy 耗时98s

我错过了什么吗?我怎样才能更快地调用 cpdef 函数 运行?

非常感谢!

它花费的时间太长,因为 pyximport 会即时编译 cython 代码(因此您也在测量从 cython 到 C 的编译以及从 C 代码到本机库的编译)。您应该测量调用已编译的代码 - 请参阅 https://cython.readthedocs.io/en/latest/src/quickstart/build.html#building-a-cython-module-using-setuptools

这不是一个有意义的测试 - 两个函数不一样:

  • Python print 打印一个字符串后跟一个换行符。我认为它会刷新输出。
  • printf 扫描字符串中的格式化字符(例如 %s),然后在没有额外换行符的情况下打印它。默认情况下 printf 是行缓冲的(即在每个新行之后刷新)。由于您从不 post 换行或刷新它,因此管理越来越大的缓冲区可能会减慢它的速度。

总而言之,不要被毫无意义的微基准测试所误导。特别是对于终端 IO,这实际上很少成为限制因素。

我强烈怀疑你的配置有问题。

我已经(部分)在 Windows 10、Python 3.10.0、Cython 0.29.26、MSVC 2022 中重现了您的测试,并得到了完全不同的结果

因为在我的测试中,Cython 代码稍快一些。我做了 2 处更改:

  • 在 hello_cy.pyx 中,为了使两个代码更接近,我添加了换行符:

      ...
      printf("%s\n", hello_world)
    
  • 在主脚本中我把函数的调用和时间的显示分开了:

      ...
      pyp = timeit.timeit(stmt=code_py, setup=imp)
      pyc = timeit.timeit(stmt=code_cy, setup=imp)
    
      print(pyp)
      print(pyc)
    

当我 运行 我得到的脚本(在你好几页之后...):

...
hello from C world
hello from C world
19.135732599999756
14.712803700007498

这看起来更像是预期的...

无论如何,我们真的不知道这里测试的是什么,因为尽可能不要测试 IO,因为它取决于程序本身之外的很多东西。