Cython中的字符串操作

2024-04-19 23:15:26 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一些代码做一些非常CPU密集的字符串操作,我正在寻找提高性能的方法。

(编辑:我正在做一些事情,比如寻找最长的公共子串,运行大量的正则表达式,这些表达式可能更好地用c语言表示为状态机,从HTML中剥离注释,诸如此类的事情。)

我目前正在研究将一些代码移植到Cython中,此前我听到了很多关于它的好消息。然而,Cython的主要关注点似乎是数值计算,而对字符串的处理几乎没有文献记载。

Unicode也可能是一个大问题。

我的问题是:

  1. 我是不是该为弦的事和Cython打交道?有没有人有在cython中进行这种处理的经验并且可以分享?
  2. 我是不是错过了赛顿医生的资料?有人知道在Cython中使用字符串的教程/参考资料/文档吗?

Tags: 方法字符串代码语言编辑表达式htmlcpu
3条回答

我对profile it的答案进行了投票,但我想补充一点:在可能的情况下,最好的优化方法是使用Python标准库或内置函数来执行您想要的任务。它们通常用C语言实现,并将提供与任何扩展大致相当的性能,包括用Cython编写的扩展。如果您的算法在Python中执行逐字符循环,那么如果可能的话,这些应该是首先要做的事情。

但是如果你的算法不能根据内置或其他现有的标准库进行修改,Cython看起来是一个合理的方法。它只是将伪Python编译成本机代码,与其他任何操作一样适合于字符串操作。但我不相信,如果您只是将惯用的Python代码交给Cython,您将看到使用Cython的巨大好处。如果您能够用C语言重写每个算法的一部分或全部,这样低级操作就不会不断地跨Python/C障碍转换变量,那么最大的好处就来了。

最后,Unicode——你已经暗示它可能是一个“大问题”,但还没有具体说明如何使用它。Cython可能会生成调用处理Unicode的相关pythonapi的C代码,因此功能不太可能受到限制。然而,在C语言中处理Unicode字符串并不简单,这可能意味着用C语言重写一些算法以获得更好的性能的想法是不值得的。许多经典的字符串算法在许多Unicode编码上根本不起作用,这些编码在传统意义上不是“字符串”,即每个字符有1个存储单元。

为了完整起见,我最后做的只是用C编写(一些)字符串操作代码

事实证明,开始编写python的c扩展是ridiculously easy。Unicode字符串只是Py_Unicode的数组,根据python构建的不同,它是int或short。

我有一个x20改进转换代码

s = re.sub(r' +', ' ', s)

对c来说,我对更复杂的regexp做了类似的改进,但是c代码很快变得非常复杂。

总的来说,重写之后我的吞吐量增加了20%。我正在寻找更多的东西重写。。。

“可笑的简单”是一个非常相对的词“开始”就是这样。在C语言中编写健壮的扩展需要非常小心地注意诸如引用计数、内存分配/释放和错误处理。赛顿为你做了很多。

Cython中的非unicode字符串要么是Python str对象,要么是一个char数组,如C中所示。您认为您需要什么Cython特定的文档?

我建议你自己试试赛松。但在您这样做之前,我强烈建议您检查您的Python代码是否效率低下。有时候你可以轻松地获得大加速。

例如,压缩空格字符。。。使用

re.sub(' +', ' ', s) # one space in pattern

这意味着,在长度为1的管路中,它将用一个空间替换一个空间。如果所有的运行都有长度1,那么它将创建一个新的替换字符串,而只需增加(或不减少,或其他)输入字符串的引用计数并将其传回。

re.sub('  +', ' ', s) # two spaces in pattern

产生完全相同的结果,可能运行得更快。。。让我们看看:

所有跑步长度1:它以3.4倍的速度跑。未显示:输入字符串越长,效果越好。

\python26\python -mtimeit -s"s='now is the winter of our discontent'; import re; x = re.compile(' +').sub" "x(' ', s)"
100000 loops, best of 3: 8.26 usec per loop

\python26\python -mtimeit -s"s='now is the winter of our discontent'; import re; x = re.compile('  +').sub" "x(' ', s)"
100000 loops, best of 3: 2.41 usec per loop

如果一次运行的长度为2,则速度比为2.5。所有的运行长度为2,速度比为1.2。从各方面考虑,一次按键投资的回报并不坏。

相关问题 更多 >