Где мой сценарий Python проводит время? Есть ли «отсутствие времени» в моем прослеживании CPROFIL / PSTATS?

StackOverflow https://stackoverflow.com/questions/2780294

Вопрос

Я пытаюсь профилировать длинный бегущий сценарий Python. Сценарий делает некоторый пространственный анализ на растровых данных, набор данных, используя модуль gdal.. Отказ Сценарий в настоящее время использует три файла, основной скрипт, который циклал по растрому пикселям find_pixel_pairs.py, простой кеш в lrucache.py и некоторые классы разных в utils.py. Отказ Я профилировал код на наборе данных умеренного размера. pstats Возвращает:

   p.sort_stats('cumulative').print_stats(20)
   Thu May  6 19:16:50 2010    phes.profile

   355483738 function calls in 11644.421 CPU seconds

   Ordered by: cumulative time
   List reduced from 86 to 20 due to restriction <20>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.008    0.008 11644.421 11644.421 <string>:1(<module>)
        1 11064.926 11064.926 11644.413 11644.413 find_pixel_pairs.py:49(phes)
340135349  544.143    0.000  572.481    0.000 utils.py:173(extent_iterator)
  8831020   18.492    0.000   18.492    0.000 {range}
   231922    3.414    0.000    8.128    0.000 utils.py:152(get_block_in_bands)
   142739    1.303    0.000    4.173    0.000 utils.py:97(search_extent_rect)
   745181    1.936    0.000    2.500    0.000 find_pixel_pairs.py:40(is_no_data)
   285478    1.801    0.000    2.271    0.000 utils.py:98(intify)
   231922    1.198    0.000    2.013    0.000 utils.py:116(block_to_pixel_extent)
   695766    1.990    0.000    1.990    0.000 lrucache.py:42(get)
  1213166    1.265    0.000    1.265    0.000 {min}
  1031737    1.034    0.000    1.034    0.000 {isinstance}
   142740    0.563    0.000    0.909    0.000 utils.py:122(find_block_extent)
   463844    0.611    0.000    0.611    0.000 utils.py:112(block_to_pixel_coord)
   745274    0.565    0.000    0.565    0.000 {method 'append' of 'list' objects}
   285478    0.346    0.000    0.346    0.000 {max}
   285480    0.346    0.000    0.346    0.000 utils.py:109(pixel_coord_to_block_coord)
      324    0.002    0.000    0.188    0.001 utils.py:27(__init__)
      324    0.016    0.000    0.186    0.001 gdal.py:848(ReadAsArray)
        1    0.000    0.000    0.160    0.160 utils.py:50(__init__)

Два верхних вызова содержат основной цикл - весь анализ. Остальные звонки суммы менее чем на 625 из 11644 секунд. Где остальные 11 000 секунд потрачены? Это все в пределах основной петли find_pixel_pairs.py? Если это так, я могу узнать, какие строки кода занимают большую часть времени?

Это было полезно?

Решение

Вы правы, что большую часть времени проводится в phes Функция на линии 49 find_pixel_pairs.py. Отказ Чтобы узнать больше, вам нужно расстаться phes в более подфункции, а затем перепрофиль.

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

Забудьте функции и измерения. Используйте эту технику. Просто запустите его в режиме отладки, и сделайте Ctrl-C несколько раз. Стек вызовов покажет вам, какие строки кода несут ответственность за время.

Добавлено: Например, пауза 10 раз. Если, как говорит EOL, 10400 секунд из 11000 проводится напрямую в phes, затем примерно 9 из этих пауз, он остановится прямо тамОтказ Если, с другой стороны, он проводит большую долю времени в некоторых подпрограмме phes, Затем вы не только увидите, где он находится в этом подпрограмме, но вы увидите строки, которые называют его, которые также несут ответственность за время и т. Д., Вверх по стеку вызовов.

Не измеряйте. Захватывать.

Время, проведенное в выполнение кода из каждой функции или метода в tottime столбец. То cumtime Метод есть tottime+ время, проведенное в функциях.

В вашем списке вы видите, что 11 000 секунд, которые вы ищете, проводятся напрямую phes функция сама. То, что он называет только около 600 секунд.

Таким образом, вы хотите найти, что требует времени в phes, нарушая его в подфункции и перепрофилирование, как предложил ~ ЮНУТБУ.

Если вы определили потенциал для узких мест в phes Функция / метод в find_pixel_pairs.py, вы можете использовать line_profiler Чтобы получить показатели профиля выполнения строки, такие как эти номера (скопированы с другой вопрос здесь):

Timer unit: 1e-06 s

Total time: 9e-06 s
File: <ipython-input-4-dae73707787c>
Function: do_other_stuff at line 4

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     4                                           def do_other_stuff(numbers):
     5         1            9      9.0    100.0      s = sum(numbers)

Total time: 0.000694 s
File: <ipython-input-4-dae73707787c>
Function: do_stuff at line 7

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     7                                           def do_stuff(numbers):
     8         1           12     12.0      1.7      do_other_stuff(numbers)
     9         1          208    208.0     30.0      l = [numbers[i]/43 for i in range(len(numbers))]
    10         1          474    474.0     68.3      m = ['hello'+str(numbers[i]) for i in range(len(numbers))]

С этой информацией вы делаете нет надо ломаться phes Вплоть в несколько подфункций, потому что вы можете видеть именно, какие строки имеют наибольшее время выполнения.

Поскольку вы упоминаете, что ваш сценарий долго бежит, я бы порекомендовал использовать line_profiler В качестве ограниченного количества методов максимально возможны, потому что в то время как профилирование добавляет дополнительные накладные расходы, профилирование линии может добавить больше.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top