J'ai le même script Python exécuté sur deux machines, sur la même entrée et donnant la même sortie. Il faut environ 7 minutes pour fonctionner sur mon ordinateur portable et 56 minutes pour fonctionner sur un serveur sur lequel je l'ai téléchargé.Comment diagnostiquer une différence flagrante dans l'exécution du script Python (agrégats pandas) entre deux machines?
Évidemment, l'environnement est différent, mais la différence de vitesse (8x!) était un peu trop flagrante pour moi de l'écrire comme différents environnements. Les deux machines ont beaucoup de mémoire, et le serveur a plus de cœurs que mon ordinateur portable, mais aussi plus de choses qui tournent dessus (et je ne pense pas que les cœurs sont importants pour cette opération). C'est normal pour moi de faire fonctionner mon ordinateur portable et le serveur. Je n'ai jamais eu une différence de vitesse de 2x, sans parler de celle de 10x.
Le script est un exemple, la plupart du travail est un pandas.DataFrame.groupby().aggregate(lambda)
, mais sur une grande table (~ 400 Mo). Comment puis-je diagnostiquer ce qui cause la différence de vitesse?
Voici ce que j'ai essayé jusqu'à présent, mais je sais que très peu à ce sujet, il peut ou ne peut pas être intéressant.
cprofile
J'ai essayé de courir python -m cProfile
dans les deux environnements pour voir si l'appel de fonction particulière prenait beaucoup de temps, mais il semblait être dans tous les domaines:
ordinateur portable:
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)
...
serveur:
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)
...
Comme il semblait être sur toute la ligne plutôt que d'une seule fonction que je pouvais isoler, j'ai essayé de voir si je pouvais réduire le problème à une minimum, complete, verifiable example ... Ce fut le meilleur que je suis:
% timeit
ordinateur portable:
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
serveur:
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
Alors cela ne capture pas tout à fait la différence de vitesse 8x. Il montre seulement une différence de vitesse de 2x.
Mais cette différence de taille (2x) me donne l'impression d'être habitué à certains facteurs environnementaux que je ne pourrai peut-être pas comprendre, comme d'autres charges sur le serveur ou quelque chose comme ça, ou différents processeurs. Si je veux effacer une différence de 2x en tant que machines différentes, cela signifie-t-il que je dois aussi accepter une différence de 8x en tant que machines différentes? Ou y a-t-il des choses plus intéressantes à creuser ici?
Conclusion:
Ma version pandas
était 0.17.1 sur mon ordinateur portable et 0,18.1 sur le serveur. J'ai comparé le même code fonctionnant sur mon ordinateur portable entre 0.17.1 et 0.18.1, et 0.17.1 a couru environ 4x aussi vite. So ~ 4x peut être attribué à cela, et ~ 2x peut être attribué aux différences de plate-forme entre l'ordinateur portable et le serveur.
Il y a beaucoup de choses qui pourraient se passer ici ... mais je vais demander l'évidence: utilisent-ils tous les deux le même interpréteur Python * (c'est-à-dire qu'il n'y a pas Python 2.11.7 et l'autre a Python 3.5.1)? – mwm314
Vérifiez une liste pip de modules pour les différences de version? – dartdog
Je commencerais par vérifier la version du serveur de Pandas. 'gel de pip | grep pandas' – Alexander