Python 3: разница во времени: понимание списка int vs list понимание списка int

У меня возникла проблема со временем вычисления при понимании списка. Решая его, я обнаружил, что:

In [209]: now = datetime.datetime.now()
     ...: for i in range(15):
     ...:     k = [0 for j in range(100000)]
     ...:     print(datetime.datetime.now() - now)
     ...:     
     0:00:00.004146
     0:00:00.007886
     0:00:00.011533
     0:00:00.015274
     0:00:00.019104
     0:00:00.022788
     0:00:00.026528
     0:00:00.030252
     0:00:00.033969
     0:00:00.037713
     0:00:00.041409
     0:00:00.045144
     0:00:00.048842
     0:00:00.052526
     0:00:00.056224

Нет проблем: понимание списка происходит быстро. Теперь вместо создания int, если мы создадим список int ...

In [211]: now = datetime.datetime.now()
     ...: for i in range(15):
     ...:     k = [[0] for j in range(100000)]
     ...:     print(datetime.datetime.now() - now)
     ...:     
     0:00:00.047167
     0:00:00.107979
     0:00:00.170456
     0:00:00.231888
     0:00:00.293667
     0:00:00.354984
     0:00:06.686698    <=== Taking much more time
     0:00:06.747476
     0:00:06.811326
     0:00:06.874809
     0:00:06.937590
     0:00:06.998185
     0:00:07.068399
     0:00:13.449616    <=== Taking much more time
     0:00:13.511518

Похоже, что python должен выполнять какую-то операцию каждые X итераций. Операция, которая здесь занимает много времени.

Я полагаю, это как-то связано с распределением памяти или чем-то подобным, но если кто-то, кто знает причину, захочет это объяснить, мне будет более чем интересно!

Спасибо.

Изменить: Дополнительная информация: у меня проблема в сеансе tmux на ipython. Если я открываю новое окно tmux, на ipython проблема не существует ... Итак, похоже, проблема связана с конкретным открытым окном tmux? У меня все еще есть открытая сессия, если некоторые из вас хотят кое-что попробовать ...

Итак, мы говорим, что это просто повреждено или что-то есть?

Хм ... не могу воспроизвести на python3.6 ...

cs95 11.04.2018 13:31

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

khelwood 11.04.2018 13:31
1
2
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш метод измерения неточен - у вас много накладных расходов на вызовы функций, а время выполнения print будет варьироваться при выполнении системных вызовов. Чтобы добиться лучших результатов, попробуйте что-нибудь вроде этого:

import timeit
int_res = [timeit.timeit('[0 for i in x]', setup="x = range(100000)", number=1) for i in range(1000)]
list_res = [timeit.timeit('[[0] for i in x]', setup="x = range(100000)", number=1) for i in range(1000)]
print("Ints:", min(int_res), max(int_res))
print("Lists:", min(list_res), max(list_res))

Выход:

Ints: 0.004607329028658569 0.04245903599075973
Lists: 0.015519230044446886 0.1320938270073384

Как видите, оба метода показывают одно и то же поведение.

Затем я попытался проверить гипотезу о сборщике мусора. Я сделал следующее:

import timeit
import gc
int_res = [timeit.timeit('[0 for i in x]', setup="x = range(100000); gc.collect()", number=1) for i in range(1000)]
list_res = [timeit.timeit('[[0] for i in x]', setup="x = range(100000); gc.collect()", number=1) for i in range(1000)]
print("Ints:", min(int_res), max(int_res))
print("Lists:", min(list_res), max(list_res))

Выход:

Ints: 0.004779412993229926 0.02010424993932247
Lists: 0.015465378062799573 0.03042234410531819

Здесь деталь setup= не замеряется и не дает никакого эффекта. Каждое измерение выполняется с помощью функции timeit, а затем запоминается.

Протестировал ваши функции. Это действительно из сборщика мусора! Спасибо за понимание :)

YnternetXplorer 11.04.2018 15:04

Другие вопросы по теме