以下代码在Python 3.3上运行大约需要两分钟,但是等效的VB.net版本在不到一秒的时间内运行。我在这里做的特别低效会让它在Python上变慢吗?或者它只是一个较慢的翻译? Python的数学库会慢得多吗? (将x,x1和x3初始化为浮点数没有太大区别。)
inc = 2*3*5*7
for x in range(inc,200000,inc):
n = 0
y = x * x + x
for x1 in range(x+1, y):
x2 = x1 / (x1 - x) * x
x3 = round(x2)
if abs(x2 - x3) < 0.0000001:
if x3 < x1: break
n += 1
if n > 500: print(x, n)
(我意识到有更好的算法来完成同样的事情。我有兴趣改进这个的Python实现,以便学习更多的Python。)
VB代码:
Dim x, x1, x2, x3, y As Double
Dim n As Integer
For x = 0 To 200000 Step 2 * 3 * 5 * 7
n = 0
y = x * x + x
For x1 = x + 1 To y
x2 = x1 / (x1 - x) * x
x3 = Round(x2)
If Math.Abs(x2 - x3) < 0.0000001 Then
If x3 < x1 Then Exit For
n += 1
End If
Next x1
If n > 500 Then sb.Append(x & " " & x1 & " " & x3 & " " & n & vbCrLf)
Next x
答案 0 :(得分:4)
你没有编写特别低效的代码,没有。您只是看到纯粹解释的语言(而不是特别快的语言)和编译语言之间的正常性能差异。作为证据,请考虑通过在cProfile
下运行代码生成的配置文件十五秒:
% python3 -m cProfile stackoverflow.py & pid=$\!; sleep 15; kill -INT $!
55440 608
60060 608
65520 608
69300 563
73920 527
78540 608
32855602 function calls in 14.969 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 10.557 10.557 14.969 14.969 so.py:1(<module>)
16427796 0.646 0.000 0.646 0.000 {built-in method abs}
1 0.000 0.000 14.969 14.969 {built-in method exec}
6 0.000 0.000 0.000 0.000 {built-in method print}
16427797 3.766 0.000 3.766 0.000 {built-in method round}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
您最大的成本中心似乎是round
函数,但即使只占用运行时的三分之一。这表明问题不是您自己的代码的任何特定部分,而是低效算法和慢速解释器的组合。
答案 1 :(得分:1)
问题不在于python数学--- python数学运算与任何其他语言一样快。问题是python字节码执行速度慢,这很慢。
您可以使用以下技术加快速度:
如果你想学习python,我会说numpy是要走的路,就像cython和weave一样,你将学习如何更多地编写C代码。
答案 2 :(得分:1)
你可以随时使用cython
到C
- 如果你的python代码。 (抱歉奇怪的__future__
,xrange
和百分号)我正在使用Python 2.7
和ipython notebook
。
from __future__ import division
%%timeit
inc = 2*3*5*7
for x in xrange(inc,200000,inc):
n = 0
y = x * x + x
for x1 in xrange(x+1, y):
x2 = x1 / (x1 - x) * x
x3 = round(x2)
if abs(x2 - x3) < 0.0000001:
if x3 < x1: break
n += 1
if n > 500: a,b = x,n
1 loops, best of 3: 1min 5s per loop
%load_ext cythonmagic
%%cython -f
#cython: boundscheck=False
#cython: wraparound=False
from __future__ import division
from libc.math cimport fabs
from libc.math cimport round as cround
import time
cdef int inc = 2*3*5*7
cdef int x
cdef int n
cdef int y
cdef int x1
cdef double x2
cdef double x3
cdef int a, b
t0 = time.time()
for x in range(inc,200000,inc):
n = 0
y = x * x + x
for x1 in range(x+1, y):
x2 = x1 / (x1 - x) * x
x3 = cround(x2)
if fabs(x2 - x3) < 0.0000001:
if x3 < x1: break
n += 1
if n > 500: a,b = x,n
t1 = time.time()
print "time elapsed:", t1 - t0, "sec"
time elapsed: 0.900931119919 sec
答案 3 :(得分:0)
一个快速修复是在pypy而不是python中运行它。因为pypy有一个JIT编译器,所以它会编译这些循环。
在我的机器上,pypy在36秒内完成,而python仍然没有回复。
编辑:我不确定算法是做什么的,但是如果你试图看看x2是否是一个整数,那么使用.is_integer将python3占用的时间减半,并将pypy降低到1秒。似乎在某些情况下它会返回错误的答案,但为了完整起见,我将包含代码。inc = 2*3*5*7
for x in range(inc,200000,inc):
n = 0
y = x * x + x
for x1 in range(x+1, y):
x2 = float(x1) / (x1 - x) * x
if x2.is_integer():
if x2 < x1: break
n += 1
if n > 500: print(x, n)