Выполнять оператор каждые N итераций в Python - PullRequest
15 голосов
/ 12 апреля 2011

У меня очень длинный цикл, и я хотел бы проверять состояние каждые N итераций, в моем конкретном случае у меня есть цикл из 10 миллионов элементов, и я хочу печатать короткий отчет каждую миллионную итерацию.

Итак, в настоящее время я делаю только (n - счетчик итераций):

if (n % 1000000==0):
    print('Progress report...')

, но я беспокоюсь, что замедляю процесс, вычисляя модуль на каждой итерации, поскольку одна итерация длится всего несколькомиллисекунды.

Есть ли лучший способ сделать это?Или мне вообще не стоит беспокоиться о работе модуля?

Ответы [ 8 ]

23 голосов
/ 12 апреля 2011

Как насчет того, чтобы сохранить счетчик и сбросить его на ноль, когда вы достигнете нужного числа?Добавление и проверка равенства выполняется быстрее, чем по модулю.

printcounter = 0

# Whatever a while loop is in Python
while (...):   
    ...
    if (printcounter == 1000000):
        print('Progress report...')
        printcounter = 0
    ...
    printcounter += 1

Хотя вполне возможно, что компилятор уже выполняет какую-то подобную оптимизацию для вас ... но это может дать вам некоторое спокойствие.

11 голосов
/ 12 апреля 2011

Это действительно замедляется?Вы должны попробовать и убедиться сами.Это не будет большим замедлением, но если мы говорим о наносекундах, это может быть значительным.В качестве альтернативы вы можете преобразовать один цикл из 10 миллионов в два меньших цикла:

m = 1000000
for i in range(10):
    for i in range(m):
        // do sth
    print("Progress report")
9 голосов
/ 30 октября 2015

Суп, черт? Свяжитесь со мной, если вам нужен дополнительный комментарий / объяснение:

1. Декларация о человеческом языке

x - количество пройденных итераций. n - количество итераций (вы можете использовать целое число вместо 5, блок 1; или вы можете использовать n для замены 5 для буквального n-го действия итерации, блок 2) Наша цель - делать что-то каждую x-ю итерацию и каждую 5-ю итерацию Мы проходим 100 итераций.

1. Простой для понимания код

Блок 1, минимальные переменные:

for x in 100:
    #what to do every time.
    if x % 5 == 0:
        #what to do every 5th time.

блок b, обобщение.

n = 5
for x in 100:
    #what to do every time.
    if x % n == 0:
        #what to do every 5th time.

Пожалуйста, дайте мне знать, если у вас есть какие-либо проблемы, потому что у меня не было времени проверить это после того, как я написал здесь.

3. Упражнения

  1. Если вы сделали это правильно, посмотрите, можете ли вы использовать его с функциями turtle.Pen () и turtle.forward ().
  2. Проверьте, можете ли вы использовать эту программу с функцией turtle.circle ().
  3. Проверьте чтение, чтобы попытаться улучшить ваши программы.

О модуле и других основных операторах: https://docs.python.org/2/library/stdtypes.html http://www.tutorialspoint.com/python/python_basic_operators.htm

про черепаху: https://docs.python.org/2/library/turtle.html https://michael0x2a.com/blog/turtle-examples

8 голосов
/ 12 апреля 2011

Трудно понять, как ваша система оптимизирует ваш код без тестирования.

Вы можете упростить реляционную часть, поняв, что ноль оценивается как ложный.

if(not N % 10000000)
   do stuff
2 голосов
/ 12 апреля 2011

Что-то в этом роде? :

for n in xrange(1000000,11000000,1000000):
    for i in xrange(n-1000000,n):
        x = 10/2
    print 'Progress at '+str(i)

результат

Progress at 999999
Progress at 1999999
Progress at 2999999
Progress at 3999999
Progress at 4999999
Progress at 5999999
Progress at 6999999
Progress at 7999999
Progress at 8999999
Progress at 9999999

.

EDIT

Лучше:

for n in xrange(0,10000000,1000000):
    for i in xrange(n,n+1000000):
        x = 10/2
    print 'Progress at '+str(i)

и вдохновленный от пайтона:

m = 1000000
for n in xrange(0,10*m,m):
    for i in xrange(n,n+m):
        x = 10/2
    print 'Progress at '+str(i+1)

Я предпочитаю, чтобы это было более читабельным, чем решение Пейтона. Он отображает значение в зависимости от i

2 голосов
/ 12 апреля 2011

Я бы провел некоторое тестирование, чтобы увидеть, сколько времени занимают ваши вызовы модуля. Для этого вы можете использовать timeit . Если ваши результаты указывают на необходимость сокращения времени, другой подход, который устраняет ваши вычисления модуля:

for m in xrange(m_min, m_max):
    for n in xrange(n_min, n_max):
        #do_n_stuff
    print('Progress report...')
1 голос
/ 12 апреля 2011

Это достаточно быстро, чтобы я не беспокоился об этом.

Если вы действительно хотите ускорить его, вы можете сделать это, чтобы избежать модуля

if (n == 1000000):
    n = 0
    print('Progress report...')
0 голосов
/ 12 апреля 2011

Это делает внутренний цикл скудным, и m не должен делиться на interval.

m = 10000000
interval = 1000000
i = 0
while i < m:
    checkpoint = min(m, i+interval)
    for j in xrange(i, checkpoint):
        #do something
    i = checkpoint
    print "progress"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...