如何诊断两台机器之间的Python脚本(pandas聚合)运行时间的惊人差异?

我在两台机器上运行相同的
Python脚本,在相同的输入上并提供相同的输出.在我的笔记本电脑上运行大约需要7分钟,在我上传到它的服务器上运行需要56分钟.

显然,环境是不同的,但速度的差异(8倍!)对我来说有点过于严重,只能把它写成不同的环境.两台机器都有足够的内存,服务器的内核比我的笔记本电脑多,但运行的内容也更多(另外我不认为内核对此操作很重要).在我的笔记本电脑和服务器上运行东西是正常的.我之前从未有过2倍的速度差异,更不用说10倍速了.

该脚本非常简洁,大多数工作都是pandas.DataFrame.groupby().aggregate(lambda),但是在一个大的(~400 MB)表上.

如何诊断导致速度差异的原因?

以下是我到目前为止所尝试的内容,但我对此知之甚少,所以它可能有趣也可能没有.

CPROFILE

我尝试在两个环境中运行python -m cProfile以查看是否有任何特定的函数调用需要很长时间,但它似乎是全面的:

笔记本电脑:

  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

笔记本电脑:

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

所以这并没有完全捕捉到8倍的速度差异.它只显示大约2倍的速度差异.

但这种差异的大小(2x)我觉得我习惯于粉碎某些环境因素,这些因素可能是我无法弄清楚的,就像服务器上的其他负载或类似的东西,或者不同的处理器.如果我愿意将2倍差异作为不同的机器注销,这是否意味着我还必须愿意接受8倍差异作为不同的机器?或者有更多有趣的东西要深入研究?

结论:

我的笔记本电脑上的熊猫版本是0.17.1,服务器上是0.18.1.我在笔记本电脑上运行的相同代码在0.17.1和0.18.1之间进行了比较,而0.17.1运行速度大约是4倍.所以~4x可归因于此,~2x可归因于笔记本电脑和服务器之间的平台差异.

最佳答案 我怀疑你在看两个,甚至三个不同的原因.

通过比较两个配置文件,我看到:

>相同的例程(已排序),标准分布的一部分,执行大约相同的次数,显示3倍的时差.此例程是CPU和内存绑定,没有其他需求,因此这可能表明平台差异(更快的CPU,更慢的内存,大量的页面错误和可能交换颠簸).在调用aggregate_sv_calls_by_sv_id.py时可以看到相同的情况.
>所述例程在服务器上执行少一次,这表示同一算法的运行之间存在差异.这可能与下一个元素相同,或表示某种不确定性.
>看起来是相同的例程,并在笔记本电脑和服务器上执行相同的重要次数(93),这里称为’pandas.lib.SeriesGrouper’对象的{方法’get_result’},以及groupby.py: 1885年(_aggregate_series_pure_python)那里.这意味着软件基础存在差异.

总而言之,我会说你的软件版本本身比服务器快2.5倍.然后,服务器运行脚本慢3倍.如果可以重现,2.5 * 3会给出您观察到的8倍因子.否则,原因实际上是三个而不是两个,并且上述不确定性起作用,或者服务器上的3X减速是由于随之而来的情况(例如系统负载,很可能).

点赞