dask.bag,我应该如何在同一个数据上高效地运行多个计算
我正在处理大量数据,大部分时间都花在加载数据和解析json/任何东西上。我想用一次扫描收集整个数据集的简单统计数据 我希望我可以使用以下模式在计算中使用图形简化:dask.bag,我应该如何在同一个数据上高效地运行多个计算,dask,Dask,我正在处理大量数据,大部分时间都花在加载数据和解析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 =
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
解决这类问题有一个共同的模式吗?简短回答
导入并运行以下程序,事情应该会更快
from dask.distributed import Client
c = Client()
确保已安装dask.distributed
conda install dask distributed -c conda-forge
# or
pip install dask distributed --upgrade
尽管需要注意,但如果在文件底部而不是在顶层,则必须在中执行此操作:
from ... import ...
if __name__ == '__main__':
c = Client()
# proceed with the rest of your dask.bag code
长话短说
Dask有多种调度器。默认情况下,Dask.bag使用多处理调度程序,但也可以轻松地使用其他调度程序。有关更多信息,请参阅
多处理调度程序在单独的进程中工作,然后在必要时将这些结果带回主进程。对于简单的线性工作负载,如b.map(…).filter(…).frequencies()
任务都可以融合到一个单独的任务中,该任务进入一个进程,进行计算,然后返回非常小的结果
但是,当工作负载具有任何类型的分叉(如您所描述的)时,多处理调度程序必须将数据发送回主进程。根据数据的不同,这可能会很昂贵,因为我们需要在对象在进程之间移动时序列化它们。Dask中的基本多处理调度程序没有数据局部性的概念。一切都由中央进程协调
幸运的是,他更聪明,可以轻松处理这些情况。当您在没有任何参数的情况下运行dask.distributed.Client()
时,您将在计算机上创建一个本地进程“集群”。这样做还有很多其他好处;例如,如果您导航到,您将被视为运行所有计算