Hydra Ray Launcher 插件实战指南:在本地集群与 AWS EC2 上并行执行 Sweep 任务
2026/9/16 16:18:37 网站建设 项目流程

Hydra Ray Launcher 插件实战指南:在本地集群与 AWS EC2 上并行执行 Sweep 任务

【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra

Hydra Ray Launcher 插件为 Hydra 提供了两个开箱即用的启动器(Launcher):ray_awsray,分别用于将 multirun 任务远程提交到 AWS EC2 上的 Ray 集群,以及在本地机器或既有 Ray 集群上并行执行任务。阅读完本文,你将掌握插件的安装方式、两种启动器的完整配置模型、集群生命周期与日志的管理手段,以及如何借助sync_up/sync_down在远程与本地之间同步代码和产物,从而把 Hydra 的配置驱动实验能力无缝延伸到 Ray 生态。

插件概览:两个 Launcher,一套配置哲学

ray_awslauncher 构建在 Ray 的 Autoscaler SDK(ray.autoscaler.sdk)之上,负责在 AWS 上创建、更新并最终拆除 EC2 集群,把任务调度到该远程集群执行;raylauncher 则直接通过ray.init()连接本地机器或既有的 Ray 集群,不需要任何云资源。

两个 launcher 都遵循 Hydra 的插件配置规范:安装插件后,Hydra 会自动在hydra/launcher配置组下注册rayray_aws两个选项。从源码看,这一注册动作发生在 _config.py,通过ConfigStoreRayLauncherConfRayAWSLauncherConf两个结构化配置节点分别存入hydra/launcher组:

config_store.store( group="hydra/launcher", name="ray", node=RayLauncherConf, provider="ray_launcher", ) config_store.store( group="hydra/launcher", name="ray_aws", node=RayAWSLauncherConf, provider="ray_launcher", )

这两个配置节点的入口分别指向 ray_launcher.py 中的RayLauncher和 ray_aws_launcher.py 中的RayAWSLauncher。二者都继承自 Hydra 的Launcher基类(定义于 launcher.py),并实现setup()launch()两个核心方法——这也意味着你可以用标准的--multirun方式触发它们。

安装

插件以独立 Python 包形式发布,安装命令:

$ pip install hydra-ray-launcher --upgrade

安装完成后,无需任何额外注册,即可在命令行中通过hydra/launcher=ray_awshydra/launcher=ray启用对应启动器。

使用方法

启用方式有两种:命令行参数覆盖,或在配置文件 defaults 中 override。

命令行方式:

$ python my_app.py --multirun hydra/launcher=ray_aws

配置文件方式:

defaults: - override hydra/launcher: ray_aws

其中--multirun是触发 sweep 的关键:Hydra 只有在 multirun 模式下才会真正调度多个任务。关于插件的标准配置方式,可参考 configuring_plugins 一文。

ray_awsLauncher:在 AWS EC2 上运行任务

前置条件

ray_aws构建在 Ray Autoscaler SDK 之上,使用前需要满足两个条件:

  1. 配置好 AWS 凭据(~/.aws/credentials~/.aws/config),可参考 AWS CLI 的配置文件说明;
  2. 你的 AWS 凭据必须具备 EC2 与 IAM 的相关权限——Autoscaler SDK 需要调用 EC2 创建/查询实例、IAM 管理密钥对等接口,权限不足会导致集群创建失败。

配置模型与默认值

Autoscaler SDK 期望一份 EC2 集群配置,Hydra 将其完整 schema 化到了 _config.py 中,全部字段均有合理的默认值,因此你可以在不写任何集群配置的情况下直接跑通示例。

执行下面的命令可以查看ray_awslauncher 的完整生效配置:

$ python my_app.py hydra/launcher=ray_aws --cfg hydra -p hydra.launcher

该命令输出的配置如下(节选自插件源码中 _config.py 的默认值):

# @package hydra.launcher _target_: hydra_plugins.hydra_ray_launcher.ray_aws_launcher.RayAWSLauncher env_setup: pip_packages: omegaconf: ${ray_pkg_version:omegaconf} hydra_core: ${ray_pkg_version:hydra} ray: ${ray_pkg_version:ray} cloudpickle: ${ray_pkg_version:cloudpickle} pickle5: 0.0.11 hydra_ray_launcher: 1.2.0.dev1 commands: - conda create -n hydra_${python_version:micro} python=${python_version:micro} -y - echo 'export PATH="$HOME/anaconda3/envs/hydra_${python_version:micro}/bin:$PATH"' >> ~/.bashrc ray: init: address: null remote: {} cluster: cluster_name: default min_workers: 0 upscaling_speed: 1.0 max_workers: 1 initial_workers: 0 autoscaling_mode: default target_utilization_fraction: 0.8 idle_timeout_minutes: 5 docker: image: '' container_name: '' pull_before_run: true run_options: [] provider: type: aws region: us-west-2 availability_zone: us-west-2a,us-west-2b cache_stopped_nodes: false key_pair: key_name: hydra-${oc.env:USER,user} auth: ssh_user: ubuntu available_node_types: ray.head.default: resources: {} node_config: InstanceType: m5.large ImageId: ami-0a2363a9cff180a64 ray.worker.default: min_workers: 0 max_workers: 2 resources: {} node_config: InstanceType: m5.large ImageId: ami-0a2363a9cff180a64 InstanceMarketOptions: MarketType: spot head_node_type: ray.head.default file_mounts: {} initialization_commands: [] cluster_synced_files: [] setup_commands: [] head_setup_commands: [] worker_setup_commands: [] head_start_ray_commands: - ray stop - ulimit -n 65536;ray start --head --port=6379 --object-manager-port=8076 --autoscaling-config=~/ray_bootstrap_config.yaml worker_start_ray_commands: - ray stop - ulimit -n 65536; ray start --address=$RAY_HEAD_IP:6379 --object-manager-port=8076 run_env: auto stop_cluster: true sync_up: source_dir: null target_dir: null include: [] exclude: [] sync_down: source_dir: null target_dir: null include: [] exclude: [] logging: log_style: auto color_mode: auto verbosity: 0 create_update_cluster: no_restart: false restart_only: false no_config_cache: false teardown_cluster: workers_only: false keep_min_workers: false

配置分五大块,各有明确职责:

  • env_setup:集群上环境的准备动作。pip_packages会通过ray_pkg_version解析器(在 _config.py 中注册)自动对齐本地各依赖的版本,再结合commands中创建 conda 环境、写~/.bashrc的命令,保证远程环境与本地一致。从 _core_aws.py 的launch()实现看,这些命令会被拼装为pip install <package>==<version>后合并进cluster.setup_commands,随集群创建一并执行;
  • ray.cluster:完整的 Ray Autoscaler 集群配置,与 Ray 官方ray-schema.json一一对应;
  • sync_up / sync_down:基于 rsync 的代码与产物双向同步;
  • logging / create_update_cluster / teardown_cluster:分别控制 Ray 日志、集群创建/更新与拆除行为。

集群自动扩缩容关键参数

ray.cluster中与扩缩容直接相关的字段值得逐一说明(对应 _config.py 中的RayClusterConf):

参数默认值含义
cluster_namedefault集群的唯一标识
min_workers0除 head 节点外最少启动的 worker 数(≥ 0)
max_workers1最多启动的 worker 数,优先级高于min_workers
initial_workers0集群首次创建时启动的 worker 数
upscaling_speed1.0扩缩容速度系数,数值越大扩容越快
target_utilization_fraction0.8扩到目标资源利用率,必须小于 1.0 才会触发扩容
idle_timeout_minutes5节点空闲超过该分钟数即被移除
autoscaling_modedefaultdefaultaggressive
head_node_typeray.head.default指定 head 节点类型
provider.typeaws云提供商类型

available_node_types定义了允许的节点类型及其资源、实例规格。默认配置中 head 节点使用按需的m5.large,worker 节点同样为m5.large但采用 spot 实例(InstanceMarketOptions.MarketType: spot),以降低成本。file_mountscluster_synced_filesinitialization_commandssetup_commands等字段与 Ray Autoscaler 的语义完全一致,可用于分发数据文件、执行初始化脚本。

一个最小的运行示例

仓库中的 examples/simple 目录提供了可直接运行的示例应用,其配置文件 config.yaml 只是 override 了 launcher:

defaults: - override hydra/launcher: ray_aws task: 1

应用本体 my_app.py 是一个标准的 Hydra 应用:读取cfg.task后打印日志并休眠 1 秒。运行命令与输出如下:

$ python my_app.py --multirun task=1,2,3 [HYDRA] Ray Launcher is launching 3 jobs, [HYDRA] #0 : task=1 [HYDRA] #1 : task=2 [HYDRA] #2 : task=3 [HYDRA] Pickle for jobs: /var/folders/n_/9qzct77j68j6n9lh0lw3vjqcn96zxl/T/tmpqqg4v4i7/job_spec.pkl Cluster: default ... INFO services.py:1172 -- View the Ray dashboard at http://localhost:8265 (pid=3374) [__main__][INFO] - Executing task 1 (pid=3374) [__main__][INFO] - Executing task 2 (pid=3374) [__main__][INFO] - Executing task 3 ... [HYDRA] Stopping cluster now. (stop_cluster=true) [HYDRA] Deleted the cluster (provider.cache_stopped_nodes=false) Destroying cluster. Confirm [y/N]: y [automatic, due to --yes] ... No nodes remaining.

从输出可以看到完整的执行链路:任务规格被序列化为job_spec.pkl上传到远端,集群创建后各任务在 worker 上并行执行(可通过 Ray dashboard 观察),任务全部完成后插件默认自动拆除集群。这一流程对应的底层实现位于 _core_aws.py:所有 sweep 配置、任务函数与 Hydra 的 singleton 状态会被cloudpickle打包进job_spec.pkl,交由远端 _remote_invoke.py 反序列化后逐任务执行。

多模块应用的代码与产物同步(sync_up / sync_down)

如果应用依赖多个模块,单文件上传便不够了,此时需要配置hydra.launcher.sync_up将依赖模块同步到远程集群;任务结束后,如需将远程产物取回本地,则配置hydra.launcher.sync_down。该功能构建在rsync之上,includeexclude的语义与 rsync 完全一致,二者可以组合实现“只上传/下载需要的文件”的白名单效果。

仓库中的 examples/upload_download 演示了这一能力。训练脚本 train.py 从model.my_model导入MyModel(多模块依赖),并在cfg.checkpoint_path目录下保存 checkpoint 文件。其 launcher 配置 custom_ray_aws.yaml 如下:

defaults: - ray_aws sync_up: # source_dir 可以是相对路径(相对于运行命令的目录),也支持绝对路径 source_dir: '.' # target_dir 保持 null:文件会被同步到远端临时目录, # 任务结束后临时目录自动清理。 # 推荐同步代码/产物时保持 null,这样无需在远端配置 $PYTHONPATH include: ['model', '*.py'] # 无需上传配置文件 exclude: ['*'] sync_down: include: ['*.pt', '*/'] # 无需下载配置文件 exclude: ['*']

这里的关键技巧:sync_up.target_dir留空时,代码被同步到远端临时目录(该目录随任务结束自动清理),临时目录会自动加入PYTHONPATH,因此你无需手动配置远端环境变量。sync_down则把远程checkpoint目录下的.ptcheckpoint 文件下载回本地。运行效果:

$ python train.py --multirun random_seed=1,2,3 [HYDRA] Ray Launcher is launching 3 jobs, [HYDRA] #0 : random_seed=1 [HYDRA] #1 : random_seed=2 [HYDRA] #2 : random_seed=3 [HYDRA] Pickle for jobs: /var/folders/n_/9qzct77j68j6n9lh0lw3vjqcn96zxl/T/tmptdkye9of/job_spec.pkl Cluster: default ... INFO services.py:1172 -- View the Ray dashboard at http://localhost:8265 (pid=1772) [__main__][INFO] - Start training... (pid=1772) [INFO] - Init my model (pid=1772) [INFO] - Created dir for checkpoints. dir=checkpoint (pid=1772) [__main__][INFO] - Start training... (pid=1772) [INFO] - Init my model (pid=1772) [INFO] - Created dir for checkpoints. dir=checkpoint (pid=1772) [__main__][INFO] - Start training... (pid=1772) [INFO] - Init my model (pid=1772) [INFO] - Created dir for checkpoints. dir=checkpoint Loaded cached provider configuration ... [HYDRA] Output: receiving file list ... done 16-32-25/ 16-32-25/0/ 16-32-25/0/checkpoint/ 16-32-25/0/checkpoint/checkpoint_1.pt 16-32-25/1/ 16-32-25/1/checkpoint/ 16-32-25/1/checkpoint/checkpoint_2.pt 16-32-25/2/ 16-32-25/2/checkpoint/ 16-32-25/2/checkpoint/checkpoint_3.pt ... [HYDRA] Stopping cluster now. (stop_cluster=true) [HYDRA] Deleted the cluster (provider.cache_stopped_nodes=false) Destroying cluster. Confirm [y/N]: y [automatic, due to --yes] ... No nodes remaining.

从实现上看,_core_aws.py 会在任务执行前通过sdk.rsyncsource_dir(可相对可绝对,_get_abs_code_dir会把相对路径拼接为绝对路径)按include/exclude规则同步到远端临时目录,任务结束后再按 L175-L202 的逻辑把远端输出目录(默认是 sweep 输出目录)同步回本地sweep.dir。rsync 对应的 CLI 等价形式为:

rsync {source} {target} --include={include} --exclude={exclude}

source/target谁在本地、谁在远端,取决于sync_up(本地→远端)还是sync_down(远端→本地)。

集群生命周期管理

插件提供三组 flag 精细控制集群从创建到拆除的完整生命周期(默认行为与覆盖方式见 _core_aws.py 中stop_cluster分支的实现)。

默认设置(无需在命令行指定):任务在远端执行完毕后删除集群:

hydra.launcher.stop_cluster=true hydra.launcher.ray.cluster.provider.cache_stopped_nodes=false hydra.launcher.teardown_cluster.workers_only=false hydra.launcher.teardown_cluster.keep_min_workers=false

任务结束后保持集群运行(便于复用作下一次实验,但会产生持续费用):

hydra.launcher.stop_cluster=false

EC2 实例的关机/终止行为由hydra.launcher.ray.cluster.provider.cache_stopped_nodeshydra.launcher.teardown_cluster.workers_only组合决定:

cache_stopped_nodesworkers_only行为
falsefalse所有节点被终止
falsetrue保留 head 节点运行,仅终止 worker 节点
truefalse保留 head 与 worker 节点,并全部停机
truetrue保留 head 与 worker 节点,仅停止 worker 节点

保留hydra.launcher.ray.cluster.min_workers个 worker 节点、删除其余 worker 节点:

hydra.launcher.teardown_cluster.keep_min_workers=true

集群创建/更新行为控制

插件还允许你控制ray up过程中"跑 setup、重启 Ray、用缓存"这三个环节的取舍,对应 Ray SDK 的create_or_update_cluster参数(见 _config.py 中的RayCreateOrUpdateClusterConf):

默认配置:执行 setup 命令、重启 Ray,并使用配置缓存(如可用):

hydra.launcher.create_update_cluster.no_restart=false hydra.launcher.create_update_cluster.restart_only=false hydra.launcher.create_update_cluster.no_config_cache=false

更新集群配置时跳过重启 Ray 服务(避免中断运行中的任务,可用来动态调整 autoscaler 配置):

hydra.launcher.create_update_cluster.no_restart=true

跳过 setup 命令、只重启 Ray(不可与no_restart同时使用):

hydra.launcher.create_update_cluster.restart_only=true

禁用配置缓存、强制从云提供商处完整重新解析环境设置:

hydra.launcher.create_update_cluster.no_config_cache=true

Ray 日志配置

ray_aws通过hydra.launcher.logging控制 Ray SDK 的configure_logging行为(对应 _config.py 中的RayLoggingConf,最终在 _core_aws.py 中调用sdk.configure_logging(**logging_config)):

默认配置:使用最低 verbosity,自动检测是否启用 pretty-print 与彩色输出:

hydra.launcher.logging.log_style="auto" hydra.launcher.logging.color_mode="auto" hydra.launcher.logging.verbosity=0

关闭 pretty-print(record风格输出,不带格式化):

hydra.launcher.logging.log_style="record"

关闭彩色输出:

hydra.launcher.logging.color_mode="false"

提高 Ray 日志详细程度:

hydra.launcher.logging.verbosity=3

log_style的可选值auto/pretty/record定义于 _config.py,其中auto在 stdin 不是 TTY 时会自动退化为非 pretty 输出;color_mode的可选值true/false/auto见 L56-L63;verbosity从 0(minimal)到 3(very_very_verbose)共四级,见 L66-L74。

rayLauncher:在本地机器或既有集群上运行任务

raylauncher 不需要任何云资源,适用于本地开发调试、或把任务提交到已经运行的 Ray 集群。它的配置模型更轻量,仅包含ray.initray.remote两个字段(见 _config.py):

@dataclass class RayConf: init: Dict[str, Any] = field(default_factory=lambda: {"address": None}) remote: Dict[str, Any] = field(default_factory=dict)

默认情况下ray.init(address=None)会在本地启动一个新的 Ray 集群。运行方式与ray_aws完全一致:

$ python my_app.py --multirun hydra/launcher=ray [HYDRA] Ray Launcher is launching 1 jobs, sweep output dir: multirun/2020-11-10/15-16-28 [HYDRA] Initializing ray with config: {} INFO services.py:1164 -- View the Ray dashboard at http://127.0.0.1:8266 [HYDRA] #0 : (pid=97801) [__main__][INFO] - Executing task 1

从 _core.py 的实现可以看到,ray_cfg.init会被解析后传入start_ray,随后每个 sweep 任务通过launch_job_on_ray包装成ray.remote调用并收集结果。

如果本地已存在运行的 Ray 集群,可以通过hydra.launcher.ray.init.address指定地址连接它:

$ python my_app.py --multirun hydra/launcher=ray hydra.launcher.ray.init.address=localhost:6379 [HYDRA] Ray Launcher is launching 1 jobs, sweep output dir: multirun/2020-11-10/15-13-32 [HYDRA] Initializing ray with config: {'num_cpus': None, 'num_gpus': None, 'address': 'localhost:6379'} INFO worker.py:633 -- Connecting to existing Ray cluster at address: 10.30.99.17:6379 [HYDRA] #0 : (pid=93358) [__main__][INFO] - Executing task 1

注意输出中Initializing ray with config展示的num_cpus/num_gpus字段——它们同样可以通过hydra.launcher.ray.init传递。

配置ray.init()ray.remote()

raylauncher 构建在 Ray 的ray.init()ray.remote()两个 API 之上。通过覆盖hydra.launcher.ray.inithydra.launcher.ray.remote,你可以精确控制 Ray 运行时的行为:

$ python my_app.py --multirun hydra/launcher=ray \ hydra.launcher.ray.init.address=localhost:6379 \ hydra.launcher.ray.init.num_cpus=4 \ hydra.launcher.ray.init.num_gpus=0 \ hydra.launcher.ray.remote.memory=1024000000

其中init下的字段(如addressnum_cpusnum_gpusmemory等)与ray.init()的参数一一对应,remote下的字段则对应@ray.remote装饰器的资源配置参数。如果你需要为不同任务定制差异化资源,可以为每个任务单独设置ray.remotenum_cpus/num_gpus等值。

测试验证与运行限制

插件自带测试 test_ray_launcher.py,用于验证raylauncher 在本地集群上的行为;而 ray_aws_launcher_tests_disabled.py 从文件名即可看出,AWS 相关测试默认是禁用的——因为创建/拆除真实 EC2 集群会产生云费用且依赖真实 AWS 凭据。这提示我们:ray_aws的功能验证需要真实的 AWS 环境,本地开发阶段建议优先使用raylauncher 打通任务逻辑。

小结

Hydra Ray Launcher 插件把"配置即实验"的理念带入了 Ray 生态:raylauncher 让本地/既有集群上的 multirun 变成一行命令,ray_awslauncher 则把同样的一行命令延伸到 AWS EC2 上的弹性集群,并借助 schema 化的配置模型把 Autoscaler 的复杂参数、集群生命周期、代码与产物同步全部纳入 Hydra 的覆盖语法之下。无论你是想在本地快速并行跑参数扫描,还是需要按需在云端拉起带 spot worker 的集群跑大规模实验,都可以从本文给出的默认配置出发,用 override 逐步定制出自己的 Ray 训练流水线。

【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询