У меня есть код python, который имеет много классов. Я использовал cProfile
, чтобы узнать, что общее время запуска программы составляет 68 секунд. Я обнаружил, что следующая функция в классе под названием Buyers
занимает около 60 секунд этих 68 секунд. Мне нужно запустить программу примерно 100 раз, поэтому любое увеличение скорости поможет. Можете ли вы предложить способы увеличить скорость, изменив код? Если вам нужна дополнительная информация, которая поможет, сообщите мне.Увеличение скорости кода python
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
и utility
в качестве своих атрибутов.
EDIT - responsed добавил
----------------------------------- -
Большое спасибо за предложения. Вот ответ на некоторые вопросы и предложения, которые люди любезно делают . Я не пробовал их всех, но попробую других и напишу позже.
(1) @amber - функция доступна 80 000 раз.
(2) @gnibbler и другие - self.people - это список объектов Person в памяти. Не подключен к базе данных.
(3) @Hugh Ботвелл
cumtime принятые исходной функции - 60,8 с (доступ к 80000 раз)
cumtime, принятого новой функции с локальными функциональными псевдонимами как предложено - 56,4 с (доступ 80000 раз)
(4) @rotoglup и @Martin Томас
Я не пробовал свои решения еще. Мне нужно проверить остальную часть кода, чтобы увидеть места, где я использую self.customers, прежде чем я смогу внести изменения, не добавляя клиентов в список self.customers. Но я попробую это и напишу.
(5) @TryPyPy - спасибо за ваше любезное предложение проверить код.
Позвольте мне вначале немного ознакомиться с предложениями, которые вы сделали, чтобы убедиться, что это будет возможно использовать.
EDIT 2 Некоторые предположили, что поскольку я маркировка клиентов и noncustomers в self.people
, я должен попробовать без создания отдельных списков self.customers
и self.noncustomers
с помощью добавления. Вместо этого я должен перебрать self.people
, чтобы найти количество клиентов. Я попробовал следующий код и приурочил обе функции ниже f_w_append
и f_wo_append
. Я обнаружил, что последнее занимает меньше времени, но это еще 96% времени, затраченного первым. То есть, это очень небольшое увеличение скорости.
@TryPyPy - Следующий фрагмент кода достаточно полно, чтобы проверить функцию узкого места, если ваше предложение все еще существует, чтобы проверить его с другими компиляторами.
Еще раз спасибо всем, кто ответил.
import numpy
class person(object):
def __init__(self, util):
self.utility = util
self.customer = 0
class population(object):
def __init__(self, numpeople):
self.people = []
self.cus = []
self.noncus = []
numpy.random.seed(1)
utils = numpy.random.uniform(0, 300, numpeople)
for u in utils:
per = person(u)
self.people.append(per)
popn = population(300)
def f_w_append():
'''Function with append'''
P = 75
cus = []
noncus = []
for per in popn.people:
if per.utility >= P:
per.customer = 1
cus.append(per)
else:
per.customer = 0
noncus.append(per)
return len(cus)
def f_wo_append():
'''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
EDIT 3: Кажется NumPy проблема
Это в ответ на то, что ниже, сказал Джон Мачин. Ниже вы видите два способа определения класса Population
. Я запускал программу ниже дважды, один раз с каждым способом создания класса Population
. Один использует numpy и один не использует numpy. Один без numpy занимает аналогичное время, как Джон нашел в своих прогонах. Один с numpy занимает гораздо больше времени. Мне не ясно, что экземпляр popn
создается до начала записи времени (по крайней мере, это то, что оно появляется из кода). Затем, почему версия numpy занимает больше времени. И, я думал, что numpy должно быть более эффективным. Во всяком случае, проблема, похоже, связана с numpy и не с добавлением, хотя она немного замедляет работу. Может кто-нибудь, пожалуйста, подтвердите с помощью кода ниже? Благодарю.
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: Смотрите ответы от Джона Мачин и TryPyPy
Поскольку было так много правок и изменений здесь, те, кто находится здесь в первый раз, может быть немного запутался. См. Ответы Джона Мачина и TryPyPy. Оба они могут помочь в улучшении скорости кода. Я благодарен им и другим, которые предупредили меня о медлительности append
. Поскольку в этом случае я собираюсь использовать решение Джона Мачина и не использовать numpy для создания утилит, я принимаю его ответ в качестве ответа. Тем не менее, я очень ценю указания, упомянутые TryPyPy.
+1 для профилирования перед тем, как обратиться за помощью. – Falmarri
Какова длина 'self.people'? – Apalala
Попробуйте добавить '__slots__' в класс Person –