我有一些python代码有很多类。我使用cProfile
发现运行程序的总时间是68秒。我发现在一个名为Buyers
的类中,下面的函数花费了68秒中的60秒。我必须运行程序大约100次,所以任何速度的提高都会有帮助。你能建议一些通过修改代码来提高速度的方法吗?如果你需要更多有用的信息,请告诉我。在
def qtyDemanded(self, timePd, priceVector):
'''Returns quantity demanded in period timePd. In addition,
also updates the list of customers and non-customers.
Inputs: timePd and priceVector
Output: count of people for whom priceVector[-1] < utility
'''
## Initialize count of customers to zero
## Set self.customers and self.nonCustomers to empty lists
price = priceVector[-1]
count = 0
self.customers = []
self.nonCustomers = []
for person in self.people:
if person.utility >= price:
person.customer = 1
self.customers.append(person)
else:
person.customer = 0
self.nonCustomers.append(person)
return len(self.customers)
self.people
是person
对象的列表。每个person
都有customer
和{
编辑-已添加响应
---------------------------------------
非常感谢你的建议。这是 对人们提出的一些问题和建议作出回应 制造的。我没有试过他们所有的,但会尝试其他人和回信稍后。在
(1)@琥珀色-该功能被访问80000次。在
(2)@gnibbler等人-自我。人是内存中Person对象的列表。未连接到数据库。在
(3)@休·博思韦尔
原函数占用的累计时间-60.8秒(访问80000次)
使用建议的本地函数别名的新函数获取的cumtime-56.4 s(访问80000次)
(4)@rotoglup和@Martin Thomas
我还没有试过你的解决办法。我需要检查代码的其余部分以查看我使用的位置自己的顾客在我改变不把顾客附加到自己的顾客列表。但我会试试这个然后回信。在
(5)@TryPyPy-感谢您提供的检查代码。在
让我先读一下你提出的建议,看看这些建议是否可行。在
编辑2
有人建议,由于我在self.people
中标记客户和非客户,我应该尝试不使用append创建self.customers
和{self.people
来查找客户数量。我尝试了以下代码,并对f_w_append
和{
@TryPyPy-下面的代码足够完整,可以检查瓶颈函数,以防您的报价仍然存在,以便与其他编译器一起检查它。在
再次感谢所有回复的人。在
^{pr2}$编辑3:似乎问题出在numpy
这是对johnmachin下面所说的回应。下面您将看到两种定义Population
类的方法。我运行了下面的程序两次,一次使用创建Population
类的每种方法。一个使用numpy,一个不使用numpy。一个没有纽比的人所花的时间和约翰在跑步中发现的时间相似。一个有纽比的需要更长的时间。我不清楚的是,popn
实例是在时间记录开始之前创建的(至少这是从代码中显示的)。那么,为什么新版本要花更长的时间呢。而且,我觉得纽比应该更有效率。不管怎么说,问题似乎出在numpy上,而不是append,尽管它确实会让事情慢一点。有人能用下面的代码确认一下吗?谢谢。在
import random # instead of numpy
import numpy
import time
timer_func = time.time # using Mac OS X 10.5.8
class Person(object):
def __init__(self, util):
self.utility = util
self.customer = 0
class Population(object):
def __init__(self, numpeople):
random.seed(1)
self.people = [Person(random.uniform(0, 300)) for i in xrange(numpeople)]
self.cus = []
self.noncus = []
# Numpy based
# class Population(object):
# def __init__(self, numpeople):
# numpy.random.seed(1)
# utils = numpy.random.uniform(0, 300, numpeople)
# self.people = [Person(u) for u in utils]
# self.cus = []
# self.noncus = []
def f_wo_append(popn):
'''Function without append'''
P = 75
for per in popn.people:
if per.utility >= P:
per.customer = 1
else:
per.customer = 0
numcustomers = 0
for per in popn.people:
if per.customer == 1:
numcustomers += 1
return numcustomers
t0 = timer_func()
for i in xrange(20000):
x = f_wo_append(popn)
t1 = timer_func()
print t1-t0
编辑4:查看John Machin和Trypy的答案
因为这里有这么多的编辑和更新,那些第一次在这里发现自己的人可能有点困惑。请看约翰·马钦和特雷皮的答案。这两种方法都有助于显著提高代码的速度。我很感谢他们和其他人,他们提醒我注意append
的缓慢。因为在这个例子中,我将使用johnmachin的解决方案,而不是使用numpy来生成实用程序,所以我接受他的回答作为答案。不过,我真的很感激崔比指出的方向。
可以使用本地函数别名来消除某些查找:
请考虑缩减您的
f_wo_append
函数:编辑回应OP的评论“”“这让事情变得更糟!修剪后的版本比我在上面发布的版本花费的时间多4倍。”“”在
这是不可能的,可以采取“4倍以上”(5倍?)。。。这是我的代码,它演示了“withoutappend”情况的显著减少,正如我所建议的,还引入了“withappend”情况的显著改进。在
^{pr2}$下面是运行它的结果(Python 2.7.1,Windows 7 Pro,“Intel Core i3 CPU 540@3.07 GHz”):
编辑3为什么numpy需要更长时间:
这就是为什么我的f_wo_append2函数花费了4倍的时间:
经验主义的证据是,这些自定义类型在用作标量时并不是很快。。。可能是因为每次使用时都需要重置浮点硬件。对于大数组,不是标量。在
你在使用其他的numpy功能吗?如果没有,就使用
random
模块。如果numpy有其他用途,您可能希望在填充设置期间将numpy.float64
强制为float
。在在优化Python代码以提高速度之后,您可以尝试许多事情。如果这个程序不需要C扩展,可以在PyPy下运行它,以从它的JIT编译器中获益。您可以尝试为可能的huge speedups生成一个C extension。{A4}甚至允许您将Python程序转换为独立的C++二进制代码。在
如果你能为基准测试提供足够的代码,我愿意在这些不同的优化场景下为你的程序计时
编辑:首先,我必须同意其他所有人的观点:你确定你测量时间正确吗?示例代码在0.1秒内运行了100次,因此很有可能是时间错误,或者是您遇到了瓶颈(IO?)代码示例中不存在。在
也就是说,我做了30万人,所以时间是一致的。以下是由CPython(2.5)、PyPy和Shed Skin共享的改编代码:
使用PyPy运行与使用CPython运行一样简单,只需键入“PyPy”而不是“python”。对于SUPE外壳,必须转换为C++,编译和运行:
^{pr2}$下面是Cython-ized代码:
为了建造它,有一个设置.py像这个:
您可以使用以下方法构建它: pythonsetupfaster.py构建扩展--就地
然后测试: python-c“导入cymak更快;打印cymak更快。文件;cymakeester.main()”
每个版本的计时运行了五次,其中Cython是最快和最容易使用的代码生成器(shedskin的目标是更简单,但隐藏的错误消息和隐式静态类型使其更难使用)。至于最佳值,PyPy在没有代码更改的情况下,在计数器版本中提供了令人印象深刻的加速。在
编辑:a和更有意义的计时,针对80000个电话,每个电话300人:
脱皮最快,PyPy超过Cython。与CPython相比,这三种方法都能大大加快速度。在
相关问题 更多 >
编程相关推荐