Ray项目中使用Dask进行分布式计算的技术指南

Ray项目中使用Dask进行分布式计算的技术指南

ray ray-project/ray: 是一个分布式计算框架,它没有使用数据库。适合用于大规模数据处理和机器学习任务的开发和实现,特别是对于需要使用分布式计算框架的场景。特点是分布式计算框架、无数据库。 ray 项目地址: https://gitcode.com/gh_mirrors/ra/ray

引言

在分布式计算领域,Ray和Dask都是广受欢迎的Python库。Ray作为一个通用的分布式计算框架,提供了强大的任务调度和执行能力;而Dask则专注于数据分析领域,提供了类似NumPy和Pandas的接口来处理大规模数据。本文将详细介绍如何在Ray项目中使用Dask进行分布式计算,充分发挥两者的优势。

Dask与Ray的集成概述

Dask的核心是一个任务调度系统,它可以将复杂的计算任务分解为有向无环图(DAG)并高效执行。Ray同样提供了强大的分布式任务执行能力。通过dask_on_ray调度器,我们可以让Dask的任务在Ray集群上执行,从而获得Ray的分布式优势。

版本兼容性

在使用Dask on Ray时,版本兼容性非常重要。以下是主要版本对应关系:

  • Ray 2.40.0及以上版本:
    • Python < 3.12:Dask 2022.10.2
    • Python ≥ 3.12:Dask 2024.6.0
  • Ray 2.34.0至2.39.0:
    • Python < 3.12:Dask 2022.10.1
    • Python ≥ 3.12:Dask 2024.6.0
  • Ray 2.8.0至2.33.x:Dask 2022.10.1
  • 更早版本请参考完整版本对应表

基本使用方法

要在Ray上运行Dask任务,只需在计算时指定ray_dask_get作为调度器:

import ray
import dask.array as da
from ray.util.dask import ray_dask_get

ray.init()

# 创建Dask数组
x = da.random.random((10000, 10000))

# 在Ray上计算
result = x.sum().compute(scheduler=ray_dask_get)

注意:在Ray集群上运行时,不应使用Dask的分布式客户端,直接使用普通的Dask集合即可。

为什么选择Dask on Ray?

  1. 利用Ray特有功能:如云集群启动和共享内存存储
  2. 统一计算环境:在同一个应用中使用Dask和Ray库,无需维护两个集群
  3. 生产级执行环境:利用Ray快速、容错的分布式任务执行系统

最佳实践

大规模工作负载处理

对于大规模或内存密集型工作负载,建议:

  1. 降低scheduler_spread_threshold配置值,让调度器更倾向于将任务分散到集群
  2. 将头节点的num-cpus设置为0,避免任务调度到头节点

启动命令示例:

# 头节点
RAY_scheduler_spread_threshold=0.0 ray start --head --num-cpus=0

# 工作节点
RAY_scheduler_spread_threshold=0.0 ray start --address=[head-node-address]

超出内存的数据处理

Ray的对象溢出功能允许处理大于集群内存的数据集。从Ray 1.3+开始,此功能默认启用,对象会在内存不足时自动溢出到本地磁盘。

高级特性

持久化(Persist)

Dask-on-Ray扩展了dask.persist()功能,使其行为类似于Dask Distributed的持久化语义。调用后,任务会提交到Ray集群,并返回内联在Dask集合中的Ray futures。

import dask.array as da
from ray.util.dask import ray_dask_get

x = da.random.random((10000, 10000))
x = x.persist(scheduler=ray_dask_get)  # 立即开始计算

# 后续操作会更快,因为x已经计算完成
result1 = x.sum().compute()
result2 = x.mean().compute()

资源注解与任务选项

通过Dask的注解API,可以为特定Dask操作指定资源或其他Ray任务选项:

from dask import annotate

with annotate(ray_remote_args={"num_gpus": 1}):
    # 这个操作将在有GPU的节点上执行
    result = x.sum().compute(scheduler=ray_dask_get)

注意:可能需要禁用图优化,因为它可能会破坏注解。

DataFrame洗牌优化

Dask-on-Ray提供了一个DataFrame优化器,利用Ray的多返回任务能力,可以加速洗牌操作达4倍:

from ray.util.dask import dataframe_optimize

with dask.config.set(dataframe_optimize=dataframe_optimize):
    df = dd.read_parquet(...)
    result = df.groupby('column').apply(my_func).compute()

回调机制

Dask-on-Ray扩展了Dask的回调抽象,添加了Ray特定的回调钩子,允许用户在Ray任务提交和执行生命周期中插入自定义逻辑。

回调类型

  1. ray_presubmit: 提交Ray任务前运行
  2. ray_postsubmit: 提交Ray任务后运行
  3. ray_pretask: 在Ray worker中执行Dask任务前运行
  4. ray_posttask: 在Ray worker中执行Dask任务后运行
  5. ray_postsubmit_all: 所有Ray任务提交后运行
  6. ray_finish: 所有Ray任务执行完成后运行

回调示例

计时回调示例:

from ray.util.dask import RayDaskCallback
import time

class TimerCallback(RayDaskCallback):
    def _ray_pretask(self, key, object_refs):
        return time.time()
    
    def _ray_posttask(self, key, result, pre_state):
        duration = time.time() - pre_state
        print(f"Task {key} took {duration:.2f} seconds")

结合Actor实现状态管理

回调与Actor结合可以实现状态化数据聚合,如捕获任务执行统计信息和缓存结果:

@ray.remote
class CacheActor:
    def __init__(self, threshold):
        self.cache = {}
        self.threshold = threshold
    
    def should_cache(self, key, duration):
        return duration > self.threshold
    
    def get(self, key):
        return self.cache.get(key)
    
    def put(self, key, value):
        self.cache[key] = value

class CachingCallback(RayDaskCallback):
    def __init__(self, actor, threshold):
        self.actor = actor
        self.threshold = threshold
    
    def _ray_presubmit(self, task, key, deps):
        cached = ray.get(self.actor.get.remote(key))
        if cached is not None:
            return cached
        return None
    
    def _ray_posttask(self, key, result, pre_state):
        duration = time.time() - pre_state
        if ray.get(self.actor.should_cache.remote(key, duration)):
            self.actor.put.remote(key, result)

结论

Dask-on-Ray为数据科学家和分析师提供了一个强大的工具,使他们能够利用熟悉的Dask API,同时在Ray的强大分布式执行引擎上运行计算。通过本文介绍的各种技术和最佳实践,用户可以更高效地处理大规模数据分析任务。

虽然Dask-on-Ray仍在发展中,可能无法达到直接使用Ray的性能,但它为需要在同一应用中使用Dask和Ray生态系统的用户提供了极大的便利。随着项目的不断成熟,我们可以期待更紧密的集成和更好的性能表现。

ray ray-project/ray: 是一个分布式计算框架,它没有使用数据库。适合用于大规模数据处理和机器学习任务的开发和实现,特别是对于需要使用分布式计算框架的场景。特点是分布式计算框架、无数据库。 ray 项目地址: https://gitcode.com/gh_mirrors/ra/ray

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卓巧知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值