我正在处理大量数据,大部分时间用于加载数据和解析json /等等。我想使用单次扫描收集整个数据集的简单统计信息。
我希望我可以使用以下模式在计算中使用图表简化:
parsed = read_text(files).map(parsing)
example_stat_future = parsed.map(foo).frequencies()
another_stat_future = parsed.map(bar).sum()
etc.
example_stat, another_stat = compute(example_stat_future, another_stat_future)
但是在尝试时我看到极度减速。这是我的示例代码:
from json import loads, dumps
from time import time
import dask.bag as db
print("Setup some dummy data")
for partition in range(10):
with open("/tmp/issue.%d.jsonl" % partition, "w") as f_out:
for i in range(100000):
f_out.write(dumps({"val": i, "doubleval": i * 2}) + "\n")
print("Running as distinct computations")
loaded = db.read_text("/tmp/issue.*.jsonl").map(loads)
first_val = loaded.pluck("val").sum()
second_val = loaded.pluck("doubleval").sum()
start = time()
first_val.compute()
print("First value", time() - start)
start = time()
second_val.compute()
print("Second value", time() - start)
print("Running as a single computation")
loaded = db.read_text("/tmp/issue.*.jsonl").map(loads)
first_val = loaded.pluck("val").sum()
second_val = loaded.pluck("doubleval").sum()
start = time()
db.compute(first_val, second_val)
print("Both values", time() - start)
输出
在拥有数百万件物品的数据集上,我从未完成过一次跑步,然后再花费太长时间杀死它。
Setup some dummy data
Running as distinct computations
First value 0.7081761360168457
Second value 0.6579079627990723
Running as a single computation
Both values 37.74176549911499
是否有解决此类问题的常见模式?
答案 0 :(得分:2)
导入并运行以下内容,事情应该更快
from dask.distributed import Client
c = Client()
确保已安装dask.distributed
conda install dask distributed -c conda-forge
# or
pip install dask distributed --upgrade
虽然请注意,您必须在文件底部的if __name__ == '__main__':
块内而不是顶层执行此操作:
from ... import ...
if __name__ == '__main__':
c = Client()
# proceed with the rest of your dask.bag code
Dask有各种各样的调度程序。 Dask.bag默认使用多处理调度程序,但可以轻松地使用其他调度程序。有关详细信息,请参阅this doc。
多处理调度程序在单独的进程中工作,然后在必要时将这些结果带回主进程。对于像b.map(...).filter(...).frequencies()
这样的简单线性工作负载,任务都可以融合到一个单个任务中,该任务进入一个进程,计算,然后只返回一个非常小的结果。
但是,当工作负载具有任何类型的分支(例如您描述)时,多处理调度程序必须将数据发送回主进程。根据数据的不同,这可能很昂贵,因为我们需要在对象在进程之间移动时序列化对象。 Dask中的基本多处理调度程序没有数据局部性的概念。一切都由中央过程协调。
幸运的是,Dask's distributed scheduler更加智能,可以轻松应对这些情况。当您在没有任何参数的情况下运行dask.distributed.Client()
时,您将在计算机上创建一个本地“集群”进程。这有许多其他优点;例如,如果您导航到https://localhost:8787/status,您将被视为所有计算中正在运行的dashboard。