我有一个很大的Python代码库,最近我们开始使用Cython编译。我们计划在分析后通过Cython特定的代码来优化更重的计算,但是没有对代码进行任何更改,我预计性能会保持不变。然而,已编译应用程序的速度暴跌,并且似乎情况普遍存在。方法的执行时间比之前长10%到300%不等。
我一直在尝试测试代码来寻找Cython做得不好的事情,发现字符串操作是其中之一。我的问题是,我是否做错了什么或者Cython确实有些事情做得不好?你能帮我理解为什么它这么差以及Cython可能其他做得非常糟糕的地方吗?
编辑:让我尝试澄清一下。我意识到这种字符串连接方式很糟糕;我只是注意到它有很大的速度差异,所以我发了出来(可能是个坏主意)。虽然代码库没有这种可怕的代码,但仍然大幅减速,我希望能指出Cython处理不佳的构造类型,以便我知道该从哪里入手。我已经尝试过分析,但效果并不明显。
以下是我字符串操作测试代码的参考。我知道下面的代码很糟糕且无用,但我仍然对速度差异感到震惊。
计时代码
我一直在尝试测试代码来寻找Cython做得不好的事情,发现字符串操作是其中之一。我的问题是,我是否做错了什么或者Cython确实有些事情做得不好?你能帮我理解为什么它这么差以及Cython可能其他做得非常糟糕的地方吗?
编辑:让我尝试澄清一下。我意识到这种字符串连接方式很糟糕;我只是注意到它有很大的速度差异,所以我发了出来(可能是个坏主意)。虽然代码库没有这种可怕的代码,但仍然大幅减速,我希望能指出Cython处理不佳的构造类型,以便我知道该从哪里入手。我已经尝试过分析,但效果并不明显。
以下是我字符串操作测试代码的参考。我知道下面的代码很糟糕且无用,但我仍然对速度差异感到震惊。
# pyCode.py
def str1():
val = ""
for i in xrange(100000):
val = str(i)
def str2():
val = ""
for i in xrange(100000):
val += 'a'
def str3():
val = ""
for i in xrange(100000):
val += str(i)
计时代码
# compare.py
import timeit
pyTimes = {}
cyTimes = {}
# STR1
number=10
setup = "import pyCode"
stmt = "pyCode.str1()"
pyTimes['str1'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
setup = "import cyCode"
stmt = "cyCode.str1()"
cyTimes['str1'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
# STR2
setup = "import pyCode"
stmt = "pyCode.str2()"
pyTimes['str2'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
setup = "import cyCode"
stmt = "cyCode.str2()"
cyTimes['str2'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
# STR3
setup = "import pyCode"
stmt = "pyCode.str3()"
pyTimes['str3'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
setup = "import cyCode"
stmt = "cyCode.str3()"
cyTimes['str3'] = timeit.timeit(stmt=stmt, setup=setup, number=number)
for funcName in sorted(pyTimes.viewkeys()):
print "PY {} took {}s".format(funcName, pyTimes[funcName])
print "CY {} took {}s".format(funcName, cyTimes[funcName])
使用Cython编译模块:
cp pyCode.py cyCode.py
cython cyCode.py
gcc -O2 -fPIC -shared -I$PYTHONHOME/include/python2.7 \
-fno-strict-aliasing -fno-strict-overflow -o cyCode.so cyCode.c
结果时间
> python compare.py
PY str1 took 0.1610019207s
CY str1 took 0.104282140732s
PY str2 took 0.0739600658417s
CY str2 took 2.34380102158s
PY str3 took 0.224936962128s
CY str3 took 21.6859738827s
供参考,我已经尝试过使用Cython 0.19.1和0.23.4。我使用gcc 4.8.2和icc 14.0.2编译了C代码,并尝试使用不同的标志。
PyNumber_InPlaceAdd
。 - DavidW