在Cython中优化字符串

时间:2014-04-14 15:32:30

标签: python string performance optimization cython

我试图向我们的小组展示Cython的优点,以提高Python的性能。我已经展示了几个基准测试,所有测试都只是通过以下方式加速:

  1. 编译现有的Python代码。
  2. 将cdef用于静态类型变量,特别是在内部循环中。
  3. 但是,我们的许多代码都进行字符串操作,而且我无法通过键入Python字符串来提供优化代码的好例子。

    我尝试过的一个例子是:

    cdef str a
    cdef int i,j
    for j in range(1000000):
       a = str([chr(i) for i in range(127)])
    

    但输入' a'作为字符串实际上使代码运行得更慢。我已经阅读了关于Unicode和传递字符串的文档,但我对它在我所展示的情况下的应用方式感到困惑。我们不使用Unicode - 一切都是纯ASCII。我们正在使用Python 2.7.2

    感谢任何建议。

1 个答案:

答案 0 :(得分:13)

我建议你在cpython.array.array上进行操作。最好的文档是C API和Cython源代码(参见here)。

from cpython cimport array

def cfuncA():
    cdef str a
    cdef int i,j
    for j in range(1000):
        a = ''.join([chr(i) for i in range(127)])

def cfuncB():
    cdef:
        str a
        array.array[char] arr, template = array.array('c')
        int i, j

    for j in range(1000):
        arr = array.clone(template, 127, False)

        for i in range(127):
            arr[i] = i

        a = arr.tostring()

请注意,所需的操作会因您对字符串的操作而有很大差异。

>>> python2 -m timeit -s "import pyximport; pyximport.install(); import cyytn" "cyytn.cfuncA()"
100 loops, best of 3: 14.3 msec per loop

>>> python2 -m timeit -s "import pyximport; pyximport.install(); import cyytn" "cyytn.cfuncB()"
1000 loops, best of 3: 512 usec per loop

在这种情况下,这是一个30倍的加速。


此外,FWIW,您可以将arr.tostring()替换为arr.data.as_chars[:len(arr)]并将a键入bytes,从而取消另外几μs。