У меня такой же скрипт 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 можно отнести к различиям в платформе между ноутбуком и сервером.
Здесь может быть много всего, что может происходить здесь ... но я спрошу очевидное: они оба используют * точный * тот же интерпретатор Python (то есть у одного нет Python 2.11.7, а другой имеет Python 3.5.1)? – mwm314
Проверьте список параметров модулей для различий версий? – dartdog
Я бы начал с проверки версии сервера Pandas. 'замерзание трубопровода | grep pandas' – Alexander