通过上下文管理器或IPython魔法在Dask集群上运行代码
项目描述
Afar
一个人的魔法是另一个人的工程
罗伯特·A·海因莱因
安装
可以使用pip安装afar
pip install afar
或使用conda
conda install -c conda-forge afar
它是什么?
afar
允许您使用上下文管理器和IPython魔法在远程 Dask 集群 上运行代码。例如
import afar
from dask.distributed import Client
client = Client()
with afar.run, remotely:
import dask_cudf
df = dask_cudf.read_parquet("s3://...")
result = df.sum().compute()
在上下文之外,result
是一个数据位于工作者的 Dask Future。需要result.result()
来复制数据到本地。
默认情况下,仅保存最后一个赋值。可以指定要保存哪些变量
with afar.run("one", "two"), remotely:
one = 1
two = one + 1
one
和 two
现在都是Futures。它们可以直接用于其他afar.run
上下文
with afar.run as data, remotely:
three = one + two
assert three.result() == 3
assert data["three"].result() == 3
上面的data
是一个变量名到Futures的字典。有时可能需要从这里获取数据。或者,您可以将映射传递给afar.run
以用作数据。
run = afar.run(data={"four": 4})
with run, remotely:
seven = three + four
assert run.data["seven"].result() == 7
如果您想自动将数据收集到本地(以避免调用.result()
),请使用afar.get
而不是afar.run
with afar.get, remotely:
five = two + three
assert five == 5
Jupyter中的交互性
在Jupyter Notebook、Qt控制台、JupyterLab或任何支持丰富显示的基于IPython的前端中使用afar
时,有几个增强功能。
如果最终表达式不是赋值,则将显示其丰富的repr。
with afar.run, remotely:
three + seven
# displays 10!
打印被捕获并在本地显示
with afar.run, remotely:
print(three)
print(seven, file=sys.stderr)
# 3
# 7
这些操作是通过ipywidgets
异步完成的。
魔法!
首先加载afar
魔法扩展
%load_ext afar
现在您可以使用 afar
作为行或单元格魔法。 %%afar
类似于 with afar.run, remotely:
。它可以可选地接受一个变量名列表以保存。
%%afar x, y
x = 1
y = x + 1
并且
z = %afar x + y
这是一个好主意吗?
我不知道,但使用它确实是一种乐趣 😃 !
关于动力,请参阅 https://github.com/dask/distributed/issues/4003
对于非传统语法和魔法,人们通常会持怀疑态度。 afar
既是非传统的也是神奇的,但它也工作得很好,并且出人意料地 有趣!为什么不试一试看看您认为如何?
我们仍在探索 afar
的可用性 并想听听您的看法。在您学习 afar
的过程中,请自己问一些问题,例如
- 我们能拼写得更好吗?
- 这提供了哪些机会?
- 什么是令人惊讶的?
- 什么是缺乏的?
这是一个机会的例子
on_gpus = afar.remotely(resources={"GPU": 1})
with afar.run, on_gpus:
...
现在它工作了!传递给 remotely
的关键字参数将被传递给 client.submit
。
我不知道您是否如此,但我认为这开始看起来和感觉有点好,可能还可以更好 :)
注意事项和陷阱
重复复制数据
afar
会自动从外部作用域获取所需的数据--只有所需的数据--并将其发送到 Dask 集群进行计算。由于我们不知道在调用 afar
之间本地数据是否已被修改,我们每次使用 run
或 get
时都会序列化和发送本地变量。这通常是正常的:它工作,它是安全的,并且通常足够快。但是,如果您经常使用相对较大的数据执行此操作,性能可能会受到影响,并且您可能在本地机器上使用了不必要的更多内存。
在 Dask 中,一个常见的模式是使用 scatter
将数据发送到集群,并返回一个 Future
。这有效
A = np.arange(10**7)
A = client.scatter(A)
with afar.run, remotely:
B = A + 1
# A and B are now both Futures; their data is on the cluster
另一个选项是将 data
传递给 run
run = afar.run(data={"A": np.arange(10**7)})
with afar.run, remotely:
B = A + 1
# run.data["A"] and B are now both Futures; their data is on the cluster
如果您在一个 IPython 笔记本中,这里有一个巧妙的技巧:使用 data=globals()
!
run = afar.run(data=globals())
A = np.arange(10**7)
with run, remotely:
B = A + 1
# A and B are now both Futures; their data is on the cluster
修改远程数据
与任何 Dask 工作负载一样,应小心不要修改可能被重用的远程数据。
修改本地数据
同样,在远程运行的代码无法修改本地变量。例如
d = {}
with afar.run, remotely:
d['key'] = 'value'
# d == {}
✨ 这段代码非常实验性和神奇!✨
项目详情
下载文件
为您的平台下载文件。如果您不确定选择哪一个,请了解更多关于 安装包 的信息。