基准测试 Modin#
摘要#
要对单个Modin函数进行基准测试,通常只需打开
配置变量 变量
BenchmarkMode 即可。
没有简单的方法来对更复杂的Modin工作流进行基准测试,尽管基准测试模式或在Modin对象上调用modin.utils.execute可能有用。Modin日志可能帮助你识别代码中的瓶颈,它们也可能有助于分析每个Modin函数的执行情况。
Modin的执行和基准测试模式#
Modin 的大部分执行是异步进行的,即在独立于主程序流程的单独进程中运行。一些执行也是惰性的,这意味着一旦用户调用 Modin 函数,它不会立即开始。虽然 Modin 提供了与 pandas 相同的 API,但惰性和异步执行通常使得很难判断每个 Modin 函数调用所需的时间,以及将 Modin 的性能与 pandas 和其他类似库进行比较。
注意
本文档中的所有示例均使用本页底部指定的系统。
考虑以下的ipython脚本:
import modin.pandas as pd
from modin.config import MinRowPartitionSize
import time
import ray
# Look at the Ray documentation with respect to the Ray configuration suited to you most.
ray.init()
df = pd.DataFrame(list(range(MinRowPartitionSize.get() * 2)))
%time result = df.map(lambda x: time.sleep(0.1) or x)
%time print(result)
Modin 只需要 2.68 毫秒来完成 map 操作,并且需要 3.78 秒来打印结果。然而,如果我们在 pandas 中运行这个脚本,将 import modin.pandas as pd 替换为 import pandas as pd,map 操作需要 6.63 秒,而打印结果只需要 5.53 毫秒。
pandas 和 Modin 在解释器评估后立即开始执行 map。虽然 pandas 会阻塞直到 map 完成,但 Modin 只是在远程 ray 进程中启动异步函数。在 pandas 和 Modin 中打印函数结果相当快,但在 Modin 可以打印数据之前,它必须等待所有远程函数完成。
要计时Modin执行单个操作所需的时间,通常应使用基准模式。基准模式将等待所有异步远程执行完成。您可以随时按如下方式开启基准模式:
from modin.config import BenchmarkMode
BenchmarkMode.put(True)
在基准模式下重新运行上述脚本,Modin 的 map 耗时
3.59 秒,而 print 耗时 183 毫秒。这些时间更好地
反映了 Modin 在执行时间上的分配情况。
关于基准模式的注意事项#
虽然基准代码通常适用于测量单个Modin函数调用的性能,但在Modin的异步执行提高Modin性能的情况下,它可能会低估Modin的性能。考虑以下开启基准模式的脚本:
import numpy as np
import time
import ray
from io import BytesIO
import modin.pandas as pd
from modin.config import BenchmarkMode, MinRowPartitionSize
BenchmarkMode.put(True)
start = time.time()
df = pd.DataFrame(list(range(MinRowPartitionSize.get())), columns=['A'])
result1 = df.map(lambda x: time.sleep(0.2) or x + 1)
result2 = df.map(lambda x: time.sleep(0.2) or x + 2)
result1.to_parquet(BytesIO())
result2.to_parquet(BytesIO())
end = time.time()
print(f'map and write to parquet took {end - start} seconds.')
脚本在数据帧上执行两次慢速的map操作,然后将每个结果写入缓冲区。整个脚本在基准测试模式开启时耗时13秒,但在基准测试模式关闭时仅需7秒。由于Modin可以异步运行map操作,它可以在计算第二个结果的同时开始将第一个结果写入其缓冲区。而在基准测试模式开启时,Modin必须同步执行每个函数。
如何对复杂工作流进行基准测试#
通常,为了在工作流中基准测试Modin的整体性能,您应该首先关闭基准测试模式,查看端到端的性能。Modin工作流通常以将结果写入一个或多个文件,或将一些Modin对象打印到交互式控制台结束。这些终点是确保您所需的所有Modin执行完成的自然方式。
为了测量更细粒度的性能,开启基准测试模式可能会有所帮助,但请注意,这样做可能会降低脚本的整体性能,因此可能无法反映Modin通常花费执行时间的地方,如上所述。
开启Modin日志并使用Modin日志也可以帮助您分析工作流程。Modin日志还可以详细分解每个Modin函数在每个Modin层的性能。日志模式在与基准测试模式结合使用时更为有用。
有时,如果你的工作流程没有自然的结束点,你可以直接在工作流程的最终 Modin 对象上调用 modin.utils.execute。这通常会阻塞任何异步计算:
import time
import ray
from io import BytesIO
import modin.pandas as pd
from modin.config import MinRowPartitionSize, NPartitions
import modin.utils
MinRowPartitionSize.put(32)
NPartitions.put(16)
def slow_add_one(x):
if x == 5000:
time.sleep(10)
return x + 1
# Look at the Ray documentation with respect to the Ray configuration suited to you most.
ray.init()
df1 = pd.DataFrame(list(range(10_000)), columns=['A'])
result = df1.map(slow_add_one)
# %time modin.utils.execute(result)
%time result.to_parquet(BytesIO())
将结果写入缓冲区需要9.84秒。然而,如果你在to_parquet调用之前取消注释%time modin.utils.execute(result),to_parquet只需要23.8毫秒!
注意
如果你看到任何Modin文档在未使用基准测试模式或未保证Modin完成所有异步和延迟计算的情况下吹捧Modin的速度,你应该在Modin的GitHub上提交一个问题。将异步Modin函数调用的速度与使用其他库的等效同步调用进行比较是不公平的。
附录:系统信息#
这里的示例脚本是在以下系统上运行的:
操作系统平台和发行版(例如,Linux Ubuntu 16.04): macOS Monterey 12.4
Modin 版本: d6d503ac7c3028d871c34d9e99e925ddb0746df6
Ray 版本: 2.0.0
Python 版本: 3.10.4
机器: MacBook Pro (16英寸, 2019)
处理器: 2.3 GHz 8核 Intel Core i9 处理器
内存: 16 GB 2667 MHz DDR4