我的python代码一般都很慢,这是正常的吗?

时间:2017-07-09 03:35:35

标签: python matlab performance

我最近开始自学python,并且一直在使用这种语言进行算法的在线课程。出于某种原因,我为本课程创建的许多代码都非常慢(相对于我过去创建的C / C ++ Matlab代码),我开始担心我没有正确使用python。

这是一个简单的python和matlab代码来比较它们的速度。

MATLAB

   for i = 1:100000000
        a = 1 + 1
   end 

的Python

   for i in list(range(0, 100000000)):
        a=1 + 1

matlab代码大约需要0.3秒,而python代码大约需要7秒。这是正常的吗?我对许多复杂问题的python代码非常慢。例如,作为硬件分配,我在具有大约900000个节点的图形上运行深度优先搜索,这是永远的。谢谢。

3 个答案:

答案 0 :(得分:3)

效果为not an explicit design goal of Python

  

不要过分担心性能 - 计划稍后进行优化   需要的。

这就是为什么Python集成了大量高性能计算后端引擎的原因之一,例如numpyOpenBLAS甚至CUDA,只是为了命名少。

如果您想提高性能,最好的方法是让高性能库为您做繁重的工作。优化Python中的循环(通过使用xrange而不是Python 2.7中的范围)不会给你带来非常戏剧性的结果。

以下是一些比较不同方法的代码:

  • 您原来的list(range())
  • 建议使用xrange()
  • 离开i
  • 使用numpy使用numpy array' s(向量添加)
  • 进行添加
  • 使用CUDA在GPU上添加矢量

代码:

import timeit
import matplotlib.pyplot as mplplt

iter = 100
testcode = [
    "for i in list(range(1000000)): a = 1+1",
    "for i in xrange(1000000): a = 1+1",
    "for _ in xrange(1000000): a = 1+1",
    "import numpy; one = numpy.ones(1000000); a = one+one",
    "import pycuda.gpuarray as gpuarray; import pycuda.driver as cuda; import pycuda.autoinit; import numpy;" \
    "one_gpu = gpuarray.GPUArray((1000000),numpy.int16); one_gpu.fill(1); a = (one_gpu+one_gpu).get()"
    ]
labels = ["list(range())", "i in xrange()", "_ in xrange()", "numpy", "numpy and CUDA"]

timings = [timeit.timeit(t, number=iter) for t in testcode]

print labels, timings

label_idx = range(len(labels))
mplplt.bar(label_idx, timings)
mplplt.xticks(label_idx, labels)
mplplt.ylabel('Execution time (sec)')
mplplt.title('Timing of integer addition in python 2.7\n(smaller value is better performance)')
mplplt.show()

结果(图表)在OSX上的Python 2.7.13上运行: Performance of integer addition in Python

Numpy比CUDA解决方案执行速度更快的原因是使用CUDA的开销并没有超过Python + Numpy的效率。对于更大的浮点计算,CUDA甚至比Numpy更好。

请注意,Numpy解决方案的执行速度比原始解决方案快80倍。如果你的时间是正确的,这甚至会比Matlab快......

关于DFS(Depth-afirst-Search)的最后一点说明:here是一篇关于Python中DFS的有趣文章。

答案 1 :(得分:2)

尝试使用xrange代替range

它们之间的区别在于**xrange**生成使用它们时的值而不是range,它会尝试在运行时生成静态列表。

答案 2 :(得分:0)

不幸的是,python的惊人灵活性和易用性是以降低成本为代价的。而且,对于如此大的迭代值,我建议使用itertools模块,因为它具有更快的缓存。

xrange是一个很好的解决方案,但是如果你想迭代字典等,最好使用itertools,你可以迭代任何类型的序列对象。