GPUs
内容
GPUs¶
Dask 通过几种方式与 GPU 协同工作。
自定义计算¶
许多人将 Dask 与 PyTorch 和 TensorFlow 等 GPU 加速库一起使用,以管理跨多台机器的工作负载。他们通常使用 Dask 的自定义 API,特别是 延迟 和 未来。
Dask 不需要知道这些函数是否使用 GPU。它只是运行 Python 函数。这些 Python 函数是否使用 GPU 与 Dask 无关。无论如何它都会工作。
作为一个实际的例子,你可能想查看这个演讲:
高级集合¶
Dask 还可以通过将 Dask 数组和 DataFrame 集合与 GPU 加速的数组或 DataFrame 库结合,来扩展大规模数组和 DataFrame 计算。
回想一下,Dask 数组 通过许多 NumPy 数组创建一个大数组,而 Dask DataFrame 通过许多 Pandas DataFrame 创建一个大 DataFrame。如果我们用那些库的 GPU 加速版本替换 NumPy/Pandas 组件,我们就可以在 GPU 上使用这些相同的系统,只要 GPU 加速版本在足够程度上类似于 NumPy/Pandas,以便与 Dask 互操作。
幸运的是,确实存在一些在GPU上模仿NumPy、Pandas和Scikit-Learn的库。
数据框¶
RAPIDS 库提供了一个 GPU 加速的类似 Pandas 的库,cuDF,它与 Dask DataFrame 很好地互操作并进行了测试。
如果你安装了 cuDF,那么你应该能够将一个基于 Pandas 的 Dask DataFrame 转换为一个基于 cuDF 的 Dask DataFrame,如下所示:
import cudf
df = df.map_partitions(cudf.from_pandas) # convert pandas partitions into cudf partitions
然而,cuDF 并不支持整个 Pandas 接口,因此各种 Dask DataFrame 操作将无法正常工作。请查看 cuDF API 参考 以获取当前支持的接口。
数组¶
备注
Dask 与 CuPy 的集成依赖于最近添加到 NumPy 和 CuPy 的功能,特别是在版本 numpy>=1.17
和 cupy>=6
中。
Chainer 的 CuPy 库提供了一个与 Dask Array 良好互操作的 GPU 加速的类 NumPy 库。
如果你安装了 CuPy,那么你应该能够将一个基于 NumPy 的 Dask 数组转换为基于 CuPy 的 Dask 数组,如下所示:
import cupy
x = x.map_blocks(cupy.asarray)
CuPy 相当成熟,并且严格遵循 NumPy API。然而,存在一些小的差异,这些差异可能导致 Dask Array 操作无法正常工作。请查看 CuPy 参考手册 以了解 API 兼容性。
设置¶
从上面的例子中我们可以看到,使用 Dask 与 GPU 支持的库的用户体验与使用 CPU 支持的库并没有太大不同。然而,在设置集群时,您可能需要考虑做一些改变。
限制工作¶
默认情况下,Dask允许与CPU核心数相同的任务并发运行。然而,如果你的任务主要使用GPU,那么你可能希望同时运行的任务数量要少得多。这里有几种限制并行性的方法:
使用 CLI 中的
--nthreads
关键字或在 Cluster 构造函数中使用ncores=
关键字,在您的 worker 上显式限制线程数量。使用 工作资源 并将某些任务标记为GPU任务,以便调度器将限制它们,同时将您的其余CPU核心留给其他工作。
指定每台机器的GPU¶
某些配置可能每个节点有多个GPU设备。Dask通常用于在这些设备之间平衡和协调工作。
在这些情况下,通常为每个设备启动一个 Dask 工作进程,并使用 CUDA 环境变量 CUDA_VISIBLE_DEVICES
将每个工作进程固定到首选一个设备。
# If we have four GPUs on one machine
CUDA_VISIBLE_DEVICES=0 dask-worker ...
CUDA_VISIBLE_DEVICES=1 dask-worker ...
CUDA_VISIBLE_DEVICES=2 dask-worker ...
CUDA_VISIBLE_DEVICES=3 dask-worker ...
Dask CUDA 项目包含一些方便的 CLI 和 Python 工具,用于自动化此过程。