【问题标题】:Optimizing strings in Cython在 Cython 中优化字符串
【发布时间】:2014-05-28 15:38:47
【问题描述】:

我试图向我们的团队展示 Cython 在提高 Python 性能方面的优点。我已经展示了几个基准,所有这些都通过以下方式加速:

  1. 编译现有 Python 代码。
  2. 将 cdef 用于静态类型变量,尤其是在内部循环中。

但是,我们的大部分代码都进行了字符串操作,而且我还没有想出通过键入 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

感谢任何建议。

【问题讨论】:

  • 这是 Python 2 吗?如果是这样,为什么要使用range
  • 你的意思是,使用 xrange?
  • 真的,我对最后一行代码的意思是:''.join([chr(i) for i in range(127)])
  • 我注意到声明:cdef char* a 非常快,但这会使循环中的 a 成为临时变量,因此您必须在循环中重新分配以使其工作。
  • 重新分配有问题吗?如果没有基准测试循环,您只需分配一次,对吧?

标签: python string performance optimization cython


【解决方案1】:

我建议您在cpython.array.arrays 上进行操作。最好的文档是 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。

【讨论】:

    猜你喜欢
    • 2016-11-02
    • 2012-07-28
    • 2011-08-20
    • 2019-12-04
    • 2013-09-08
    • 1970-01-01
    • 2023-03-26
    • 2015-03-31
    • 2011-06-12
    相关资源
    最近更新 更多