为控制流“计算”还是构建一个完全“延迟”的任务图更好?

Is it better to `compute` for control flow or build a fully-`delayed` task graph?

我有一个现有的 Pandas 代码库,并且刚刚开始尝试将其转换为 Dask。我仍在努力思考 Dask dataframedelayeddistributed。通过阅读 dask.delayed 文档, 理想的 情况似乎是为我想做的整套操作建立一个 task/computation 图,包括 delayed 用于用户消息的函数,然后 运行 最后在一个大块中进行所有计算。这样,当 Dask 集群执行实际工作时,调用进程不需要保持 运行。

不过,我一直面临的问题是,似乎在某些情况下这是不可行的,尤其是涉及到 Python 控制流时。例如:

df = dd.read_csv(...)
if df.isnull().any():
    # early exit
    raise ValueError()
df = some(df)
df = more(df)
df = calculations(df)
# and potentially more complex control flow

我真的不明白如何在不调用 df.isnull().any().compute() 的情况下完成这样的事情。

我现在也不知道在脚本中调用 compute()persist() 是否有任何 'bad'(违反最佳实践)。在网上查看很多示例时,它们似乎基于 experimental/Jupyter-based 环境,其中 load -> preparation -> persist() -> experimentation 似乎是标准方法。由于我有一组相对线性的操作(load -> op1 -> op2 -> ... -> opn -> save),我认为我应该尝试尽可能快地简单地安排任务而不做任何计算并避免 compute/persist,这我现在觉得已经把我带进了一个死胡同。

总而言之,我想我有两个问题想回答,第一个是 'is it bad to use compute?',第二个是 'if yes, how can I avoid compute but still have good & readable control flow?'。

只要你需要一个具体的值,调用 compute 是完全可以的。控制流就是一个很好的例子。

您可能想先在计算的主干上调用 .persist(),然后为控制流位调用 .compute(),只是为了确保您不会重复 load -> op1 -> op2 -> ... 部分计算。