2016-05-07 5 views
4

У меня такой же скрипт Python, работающий на двух машинах, на одном и том же входе и дающий тот же вывод. Для работы на моем ноутбуке требуется около 7 минут и 56 минут для запуска на сервере, на который я его загрузил.Как диагностировать вопиющую разницу в сценарии Python (pandas aggregate) между двумя машинами?

Очевидно, что окружающая среда отличается, но разница в скорости (8x!) была слишком вопиющей для меня, чтобы просто записать ее в разных средах. У обеих машин много памяти, и у сервера больше ядер, чем у моего ноутбука, но и на нем больше всего, и я не думаю, что для этой операции важно. Для меня нормально работать на моем ноутбуке и на сервере. Раньше у меня никогда не было разницы в скорости, не говоря уже о 10-кратном.

Сценарий довольно образец, большая часть работы - pandas.DataFrame.groupby().aggregate(lambda), но на большой (~ 400 МБ) таблице.

Как я могу диагностировать, что вызывает разницу в скорости?


Ниже то, что я пытался до сих пор, но я очень мало об этом знаю, так что он может или не может быть интересным.

Cprofile

Я попытался запустить python -m cProfile в обеих средах, чтобы увидеть, если какой-либо конкретный вызов функции был занимает много времени, но это, казалось, по всем направлениям:

Laptop:

ncalls tottime percall cumtime percall filename:lineno(function) 
     93 56.976 0.613 372.694 4.007 {method 'get_result' of 'pandas.lib.SeriesGrouper' objects} 
16338970 46.629 0.000 250.104 0.000 aggregate_sv_calls_by_sv_id.py:42(<lambda>) 
18442616 33.808 0.000 56.950 0.000 {sorted} 
18442645 25.395 0.000 172.113 0.000 series.py:1033(__iter__) 
78056747/78056745 15.405 0.000 15.420 0.000 {isinstance} 
18446903 14.235 0.000 34.129 0.000 dtypes.py:68(is_dtype) 
18443264 13.515 0.000 21.058 0.000 internals.py:3806(dtype) 
18442666 13.447 0.000 30.854 0.000 common.py:2192(is_datetime_or_timedelta_dtype) 
18449428 13.250 0.000 13.250 0.000 {hasattr} 
18442793 13.001 0.000 19.134 0.000 internals.py:3833(internal_values) 
... 

Сервер:

ncalls tottime percall cumtime percall filename:lineno(function) 
312253983 175.564 0.000 275.203 0.000 {isinstance} 
     93 153.294 1.648 3323.806 35.740 groupby.py:1885(_aggregate_series_pure_python) 
16338970 151.336 0.000 749.431 0.000 aggregate_sv_calls_by_sv_id.py:42(<lambda>) 
18443129 146.950 0.000 607.143 0.000 internals.py:2482(make_block) 
18442874 136.363 0.000 529.415 0.000 series.py:120(__init__) 
18443241 125.725 0.000 248.772 0.000 generic.py:2674(__setattr__) 
18442596 106.353 0.000 1336.629 0.000 internals.py:3868(get_slice) 
18442617 106.296 0.000 172.363 0.000 {sorted} 
18442596 89.203 0.000 2105.284 0.000 series.py:689(_get_values) 
18443048 84.777 0.000 91.065 0.000 base.py:506(_get_attributes_dict) 
... 

Так как казалось, по всем направлениям, а не какой-либо одной функции, я мог бы выделить, я пытался увидеть, если я мог бы свести проблему к minimum, complete, verifiable example ... Это было лучшее, что я получил:

% timeit

Laptop:

In [5]: df = pd.DataFrame(np.random.randint(10, size=(10000, 50))) 

In [6]: %timeit df.groupby(0).sum() 
100 loops, best of 3: 5.54 ms per loop 

In [7]: %timeit df.groupby(0).agg(lambda x: sum(x)) 
1 loops, best of 3: 124 ms per loop 

In [8]: %timeit df.groupby(0, 1).agg(lambda x: sum(x)) 
1 loops, best of 3: 155 ms per loop 

Сервер:

In [5]: df = pd.DataFrame(np.random.randint(10, size=(10000, 50))) 

In [6]: %timeit df.groupby(0).sum() 
100 loops, best of 3: 6.08 ms per loop 

In [7]: %timeit df.groupby(0).agg(lambda x: sum(x)) 
1 loops, best of 3: 215 ms per loop 

In [8]: %timeit df.groupby(0, 1).agg(lambda x: sum(x)) 
1 loops, best of 3: 327 ms per loop 

Так это не совсем захватывает разницу в скорости 8x. Он показывает только разницу в 2 раза.

Но этот размер разницы (2x) Я чувствую, что я привык мелить до каких-то факторов окружающей среды, которые, возможно, я не смогу понять, как и другая загрузка на сервере или что-то в этом роде, или разных процессоров. Если я готов списать разницу в 2 раза в разные машины, значит ли это, что я также должен согласиться с разницей в 8 раз, как с разными машинами? Или есть еще интересные вещи, которые нужно здесь заглянуть?


Вывод:

Моя pandas версия была 0.17.1 на моем ноутбуке и 0.18.1 на сервере. Я сравнил тот же код, который работал на моем ноутбуке между 0.17.1 и 0.18.1, а 0.17.1 работал примерно на 4 раза быстрее. Таким образом, ~ 4x можно отнести к этому, а ~ 2x можно отнести к различиям в платформе между ноутбуком и сервером.

+0

Здесь может быть много всего, что может происходить здесь ... но я спрошу очевидное: они оба используют * точный * тот же интерпретатор Python (то есть у одного нет Python 2.11.7, а другой имеет Python 3.5.1)? – mwm314

+0

Проверьте список параметров модулей для различий версий? – dartdog

+0

Я бы начал с проверки версии сервера Pandas. 'замерзание трубопровода | grep pandas' – Alexander

ответ

2

Я подозреваю, что вы смотрите на две, может быть, даже три разные причины.

Путем сравнения двух профилей, я вижу:

  • та же процедура (отсортированных), часть стандартного распределения, выполненный примерно в то же число раз, показывает разницу во времени 3X. Эта подпрограмма связана с ЦП и памятью, не имеет других потребностей, поэтому это может указывать на разницу в платформе (более быстрый процессор, более медленная память, массивная ошибка страницы и, возможно, своп). То же самое можно увидеть при звонках aggregate_sv_calls_by_sv_id.py.

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

  • то, что похоже на ту же рутину, и выполняется то же самое нетривиальное число раз (93) на ноутбуке и сервере, называется здесь и groupby.py:1885(_aggregate_series_pure_python). Это означает, что есть разница в базе программного обеспечения.

В общем, я бы выйти на конечности и сказать, что ваша версия программного обеспечения, само по себе, примерно в 2,5 раза быстрее, чем на сервере. Затем сервер запускает скрипт в 3 раза медленнее. И 2.5 * 3 дает вокруг этого 8X-фактора, который вы наблюдаете, если это воспроизводимо. В противном случае, причины на самом деле три, а не два, и указанная выше неопределенность играет роль, или 3-кратное замедление на сервере происходит из-за случайных обстоятельств (например, загрузка системы, очень вероятно).

+0

Я был поражен различиями в столбце 'filename: lineno (function)' профиля, но у меня создается впечатление, что OP только дал нам небольшую выдержку из верхней части списка. Я предполагаю, что если у нас будут полные списки, мы сможем лучше подобрать вещи в этой колонке. –

+0

Спасибо. Вы указали, что было доказательство разницы в базе программного обеспечения, заставило меня проверить более внимательно, и я обнаружил, что мой ноутбук на самом деле запускал pandas 0.17.1 при создании этих характеристик (я обновил до 0.18.1, но только потом) , Если я запустил свой конкретный код на ноутбуке, сравнив 0.17.1 и 0.18.1, 0.17.1 быстрее на 4 раза, а остальные 2x будут разностью платформы. – leekaiinthesky