完善文档内容
提交内容: 参赛承诺书:DAGRL/参赛承诺书.pdf 演示视频:通过网盘分享的文件:dagrl演示视频.mp4 链接: https://pan.baidu.com/s/1Qye3VkCK4wukO09WD3vNCw?pwd=r1vx 提取码: r1vx 复制这段内容后打开百度网盘手机App,操作更方便哦 技术文档:DAGRL/技术文档.docx 演示PPT:DAGRL/演示ppt.pptx README.md: DAGRL/README.md
提交内容:
DAGRL/参赛承诺书.pdf
DAGRL/技术文档.docx
DAGRL/演示ppt.pptx
DAGRL/README.md
DAGRL 是一个调度算法评测框架,将场景管理、方法注册、统一评测和报告生成标准化。所有调度方法——启发式(HEFT、CPOP、PEFT)、学习型(GNN-PPO)、随机基线——通过统一的 Method 接口接入,type 字段即可切换。框架不介入方法内部实现。
Method
type
@METHOD.register_module()
_base_
GNN-PPO 是框架内置的核心学习型调度算法,通过图注意力编码与强化学习在 HEFT 基础上进一步优化 makespan。策略网络由 GATv2 编码器(提取任务依赖)、ResourceEncoder(编码节点属性)、TaskResourceCrossAttention(任务-资源双向注意力交互)和 PairScorer(评分输出)四模块串联构成。训练采用三阶段递进:HEFT 专家轨迹生成 → Behavior Cloning 预训练 → Curriculum PPO 微调(50→100→300 任务渐进),推理支持 Greedy 与 Beam Search 两种策略。
实验采用 GrapheonRL STG-JSON 数据集(CC BY 4.0)。该数据集包含 180 个随机生成的唯一拓扑图,每个拓扑对应两种资源配置——homogeneous(同构,各节点处理速度相同)和 heterogeneous(异构,各节点速度差异显著)——以及三种 DAG 规模——rnc50(50 任务 / 3 节点)、rnc100(100 任务 / 5 节点)、rnc300(300 任务 / 8 节点),共 180×2×3=1080180 \times 2 \times 3 = 1080180×2×3=1080 个调度实例。我们将实例按基础拓扑图 ID 进行分层随机划分,70% 用于训练(756 个)、15% 用于验证(162 个)、15% 用于测试(162 个),确保同一拓扑的同构与异构变体始终位于同一子集,避免拓扑泄漏。
评测时,所有方法在测试集的全部 162 个场景上运行,覆盖了三种难度等级和两种资源模式的所有组合。以 HEFT makespan 为归一化分母,核心指标为 mean_ratio = M_method / M_HEFT(< 1 表示优于 HEFT)。
下表中第 2–5 列为同构资源环境下的结果,第 6–9 列为异构资源环境下的结果,第 10 列为全部 162 个测试场景的汇总。Ours 为 GNN-PPO(Greedy 推理)。
综合全部 162 个测试场景,GNN-PPO 以 mean_ratio = 0.9421 在所有方法中取得最优,优于 PEFT(0.9477)、HEFT(1.0000)、CPOP(1.1841)和 Random(2.7638)。在同构环境下,GNN-PPO 与 HEFT 表现接近(1.0110 vs 1.0000),显著优于 Random 和 CPOP;在异构环境下,GNN-PPO 以 0.8732 超越 HEFT 约 12.7%,同样略优于 PEFT(0.8753)。从难度维度看,GNN-PPO 在 rnc50 和 rnc100 的中等规模场景上优势最为突出,在 rnc300 大规模场景上仍保持对 HEFT 和 CPOP 的明显优势。Random 在异构大 DAG 场景下表现极差(mean_ratio > 4.3),说明随着动作空间的扩大,随机策略迅速失效,而学习型方法能够有效应对这种复杂性增长。
使用 uv(推荐):
curl -LsSf https://astral.sh/uv/install.sh | sh git clone https://gitlink.org.cn/IBY0zeT2tG/jysdqhxxdybdygjszyglddff.git dagrl cd dagrl conda create -n dagrl python=3.11 conda activate dagrl uv sync source .venv/bin/activate pip install -e ".[dev]"
uv 读取 pyproject.toml 自动解析依赖。需要开发依赖(pytest 等)时使用 uv sync --dev。要求 Python ≥ 3.11, PyTorch ≥ 2.5, PyTorch Geometric ≥ 2.5。
uv
pyproject.toml
uv sync --dev
python tools/prepare_data.py \ --data-root data/raw/grapheonrl \ --variants rnc50 rnc100 rnc300 \ --modes homogeneous heterogeneous
此命令扫描 data/raw/grapheonrl/ 下的所有 workflow JSON 文件,按基础图 ID 生成训练/验证/测试划分(默认 70/15/15),写入 data/splits/。
data/raw/grapheonrl/
data/splits/
python tools/eval.py \ --split test \ --methods heft cpop peft random gnn_ppo \ --gnn-checkpoint outputs/checkpoints/ppo_best_actor.pt \ --gnn-strategy greedy \ --output outputs/evaluation/test_set
输出到 outputs/evaluation/test_set/:
outputs/evaluation/test_set/
summary.json
per_instance.csv
report.md
charts/*.png
# BC 预训练 python tools/train.py config/methods/gnn_ppo_bc.py # PPO 微调 python tools/train.py config/methods/gnn_ppo_ppo.py
训练中断后恢复:在 config/methods/gnn_ppo_ppo.py 中添加一行 resume_from:
config/methods/gnn_ppo_ppo.py
resume_from
method = dict( type="GNNPPOMethod", resume_from="outputs/checkpoints/gnn_ppo", ppo=dict(total_updates=2000, ...), )
自动检测目录中步数更靠后的 checkpoint,恢复权重、优化器状态与训练步数后继续。
python tools/infer.py \ --workflow data/raw/grapheonrl/rnc50/heterogeneous/rand0000_hetero.json \ --system data/raw/grapheonrl/rnc50/heterogeneous/system.json \ --checkpoint outputs/checkpoints/ppo_best_actor.pt \ --strategy beam_search --beam-width 5
DAGRL/ ├── dagrl/ # Python 包(pip install -e .) │ ├── registry.py # Registry 类 + METHOD / DATASET 注册表 │ ├── config.py # Config.fromfile() + _base_ 多继承 │ ├── core/ # 共享基础设施 │ │ ├── schema.py # Task / ResourceNode / WorkflowInstance │ │ ├── loader.py # JSON → WorkflowInstance(含校验) │ │ ├── engine.py # ScheduleEngine(EST/EFT/可行性/放置/验证) │ │ ├── split.py # 数据划分 │ │ ├── validator.py # 调度校验 │ │ ├── export.py # 调度导出 │ │ └── features.py # 速度选择 / GPU 检测等工具函数 │ ├── methods/ # 所有调度方法(平级,不相互依赖) │ │ ├── base.py # Scenario + ScheduleResult + BaseMethod │ │ ├── heft/ / cpop/ / peft/ / random/ # 启发式基线 │ │ ├── gnn_ppo/ # GNN-PPO v1(GATv2 + Pair MLP) │ │ └── gnn_ppo_v2/ # GNN-PPO v2(GATv2 + Cross-Attention) │ ├── datasets/ # 场景管理 │ └── evaluation/ # 评测逻辑(Evaluator / Metrics / Reporter) ├── config/ # Python 配置文件 │ ├── _base_/ # 公共配置(数据集 / 运行时) │ └── methods/ # 每个方法一个可复现的训练配置 ├── tools/ # CLI 入口(prepare_data / train / eval / infer) ├── data/ # 原始数据 + 划分文件 ├── outputs/ # 生成产物(checkpoints / logs / evaluation) └── tests/ # 132 项单元测试
python tools/eval.py \ --dataset grapheonrl \ --split test \ --methods heft cpop peft random gnn_ppo \ --gnn-checkpoint outputs/checkpoints/ppo_best_actor.pt \ --gnn-strategy beam_search \ --reference heft \ --output outputs/evaluation/test_set
--methods
--reference
--gnn-checkpoint
--gnn-strategy
greedy
beam_search
--gnn-beam-width
--gnn-branch-factor
--output
python tools/train.py config/methods/gnn_ppo_bc.py # BC 预训练 python tools/train.py config/methods/gnn_ppo_ppo.py # PPO 微调
命令行覆写配置:
python tools/train.py config/methods/gnn_ppo_ppo.py --device cpu --work-dir my_experiment
配置文件示例(config/methods/gnn_ppo_ppo.py):
_base_ = ["../_base_/dataset_base.py", "../_base_/runtime_base.py"] method = dict( type="GNNPPOMethod", device="cuda", seed=42, resume_from="outputs/checkpoints/gnn_ppo", ppo=dict( total_updates=2000, episodes_per_update=16, gamma=0.99, gae_lambda=0.95, clip_range=0.2, actor_learning_rate=0.0002, critic_learning_rate=0.0003, reward_type="completion", curriculum=[ dict(phase=0, fraction=0.30, weights={"rnc50": 1.0, "rnc100": 0.0, "rnc300": 0.0}), dict(phase=1, fraction=0.40, weights={"rnc50": 0.5, "rnc100": 0.5, "rnc300": 0.0}), dict(phase=2, fraction=0.30, weights={"rnc50": 0.3, "rnc100": 0.4, "rnc300": 0.3}), ], ), )
启发式方法只需实现 schedule(scenario):
schedule(scenario)
# dagrl/methods/greedy_eft/method.py import math, time from dagrl.core.engine import ScheduleEngine from dagrl.methods.base import BaseMethod, ScheduleResult from dagrl.registry import METHOD @METHOD.register_module() class GreedyEFTMethod(BaseMethod): name = "GreedyEFT" def __init__(self): self._engine = ScheduleEngine() def schedule(self, scenario) -> ScheduleResult: t0 = time.perf_counter() instance = scenario.instance self._engine.reset(instance) N = instance.num_nodes for _ in range(instance.num_tasks): ready = self._engine.ready_tasks() best_eft, best_task, best_node = math.inf, -1, -1 for t_idx in ready: for n_idx in range(N): if not self._engine.is_feasible(t_idx, n_idx): continue est = self._engine.estimate(t_idx, n_idx) if est.feasible and est.eft < best_eft: best_eft, best_task, best_node = est.eft, t_idx, n_idx self._engine.place(best_task, best_node) validation = self._engine.validate() return ScheduleResult( scenario_id=scenario.id, method_name=self.name, makespan=self._engine.makespan(), status="feasible" if validation.valid else "invalid", schedule=self._engine.export_schedule(), wall_time_s=time.perf_counter() - t0, )
可训练方法额外实现 train()、save()、load(),通过 tools/train.py 启动训练。
train()
save()
load()
tools/train.py
实现 BaseDataset 子类,通过 @DATASET.register_module() 注册。每个 Scenario 需包含 id(唯一标识)、instance(WorkflowInstance)和 metadata(自由标注字典)。格式类似 GrapheonRL 的数据可直接复用 GrapheonRLDataset 并调整目录扫描逻辑。
BaseDataset
@DATASET.register_module()
id
instance
metadata
GrapheonRLDataset
class BaseMethod(ABC): name: str # 方法标识 schedule(scenario) → ScheduleResult # 必须实现 train(train_scenarios, val_scenarios, cfg) # 可选 save(path) / load(path) # 可选 @dataclass class ScheduleResult: scenario_id: str; method_name: str; makespan: float status: str # "feasible" | "invalid" schedule: dict # task_id → {node, start_time, finish_time} wall_time_s: float @dataclass class Scenario: id: str # "rnc50_homogeneous_rand0000" instance: WorkflowInstance # DAG + 资源 metadata: dict # {variant, mode, workflow_path, ...}
mean_ratio
win_rate_vs_reference
tie_rate_vs_reference
loss_rate_vs_reference
valid_rate
by_variant
by_mode
pytest tests/ -q # 132 项测试,覆盖 loader / DAG / HEFT / CPOP / PEFT / reward / action_mask / checkpoint 等
MIT
版权所有:中国计算机学会技术支持:开源发展技术委员会 京ICP备13000930号-9 京公网安备 11010802047560号
DAGRL: 面向异构 DAG 调度的统一训练评测框架与 GNN-PPO 算法设计与实现
1. 项目介绍
1.1 DAGRL 框架
DAGRL 是一个调度算法评测框架,将场景管理、方法注册、统一评测和报告生成标准化。所有调度方法——启发式(HEFT、CPOP、PEFT)、学习型(GNN-PPO)、随机基线——通过统一的
Method接口接入,type字段即可切换。框架不介入方法内部实现。@METHOD.register_module()一行装饰器注册,type字段实例化。新方法接入无需修改框架代码,评测即插即用_base_列表声明继承链,支持深度合并与逐层覆写。切换数据集或方法只需修改少量字段1.2 GNN-PPO 算法
GNN-PPO 是框架内置的核心学习型调度算法,通过图注意力编码与强化学习在 HEFT 基础上进一步优化 makespan。策略网络由 GATv2 编码器(提取任务依赖)、ResourceEncoder(编码节点属性)、TaskResourceCrossAttention(任务-资源双向注意力交互)和 PairScorer(评分输出)四模块串联构成。训练采用三阶段递进:HEFT 专家轨迹生成 → Behavior Cloning 预训练 → Curriculum PPO 微调(50→100→300 任务渐进),推理支持 Greedy 与 Beam Search 两种策略。
1.3 实验结果
实验采用 GrapheonRL STG-JSON 数据集(CC BY 4.0)。该数据集包含 180 个随机生成的唯一拓扑图,每个拓扑对应两种资源配置——homogeneous(同构,各节点处理速度相同)和 heterogeneous(异构,各节点速度差异显著)——以及三种 DAG 规模——rnc50(50 任务 / 3 节点)、rnc100(100 任务 / 5 节点)、rnc300(300 任务 / 8 节点),共 180×2×3=1080 个调度实例。我们将实例按基础拓扑图 ID 进行分层随机划分,70% 用于训练(756 个)、15% 用于验证(162 个)、15% 用于测试(162 个),确保同一拓扑的同构与异构变体始终位于同一子集,避免拓扑泄漏。
评测时,所有方法在测试集的全部 162 个场景上运行,覆盖了三种难度等级和两种资源模式的所有组合。以 HEFT makespan 为归一化分母,核心指标为 mean_ratio = M_method / M_HEFT(< 1 表示优于 HEFT)。
下表中第 2–5 列为同构资源环境下的结果,第 6–9 列为异构资源环境下的结果,第 10 列为全部 162 个测试场景的汇总。Ours 为 GNN-PPO(Greedy 推理)。
综合全部 162 个测试场景,GNN-PPO 以 mean_ratio = 0.9421 在所有方法中取得最优,优于 PEFT(0.9477)、HEFT(1.0000)、CPOP(1.1841)和 Random(2.7638)。在同构环境下,GNN-PPO 与 HEFT 表现接近(1.0110 vs 1.0000),显著优于 Random 和 CPOP;在异构环境下,GNN-PPO 以 0.8732 超越 HEFT 约 12.7%,同样略优于 PEFT(0.8753)。从难度维度看,GNN-PPO 在 rnc50 和 rnc100 的中等规模场景上优势最为突出,在 rnc300 大规模场景上仍保持对 HEFT 和 CPOP 的明显优势。Random 在异构大 DAG 场景下表现极差(mean_ratio > 4.3),说明随着动作空间的扩大,随机策略迅速失效,而学习型方法能够有效应对这种复杂性增长。
2. 快速开始
2.1 安装
使用 uv(推荐):
uv读取pyproject.toml自动解析依赖。需要开发依赖(pytest 等)时使用uv sync --dev。要求 Python ≥ 3.11, PyTorch ≥ 2.5, PyTorch Geometric ≥ 2.5。2.2 数据准备
此命令扫描
data/raw/grapheonrl/下的所有 workflow JSON 文件,按基础图 ID 生成训练/验证/测试划分(默认 70/15/15),写入data/splits/。2.3 评测(无需训练)
输出到
outputs/evaluation/test_set/:summary.jsonper_instance.csvreport.mdcharts/*.png2.4 训练 GNN-PPO
训练中断后恢复:在
config/methods/gnn_ppo_ppo.py中添加一行resume_from:自动检测目录中步数更靠后的 checkpoint,恢复权重、优化器状态与训练步数后继续。
2.5 单场景推理
3. 使用指南
3.1 项目结构
3.2 评测多个方法
--methods--reference--gnn-checkpoint--gnn-strategygreedy(确定性 argmax)或beam_search(K-beam 搜索)--gnn-beam-width--gnn-branch-factor--output3.3 训练 GNN-PPO
命令行覆写配置:
配置文件示例(
config/methods/gnn_ppo_ppo.py):3.4 接入新方法
启发式方法只需实现
schedule(scenario):可训练方法额外实现
train()、save()、load(),通过tools/train.py启动训练。3.5 接入新数据集
实现
BaseDataset子类,通过@DATASET.register_module()注册。每个 Scenario 需包含id(唯一标识)、instance(WorkflowInstance)和metadata(自由标注字典)。格式类似 GrapheonRL 的数据可直接复用GrapheonRLDataset并调整目录扫描逻辑。4. 参考
4.1 内置方法
4.2 核心抽象
4.3 评测指标
mean_ratiowin_rate_vs_referencetie_rate_vs_referenceloss_rate_vs_referencevalid_rateby_variantby_mode4.4 测试
License
MIT