sysHAX调度器原理剖析:智能决策算法如何实现资源最优利用

sysHAX调度器原理剖析:智能决策算法如何实现资源最优利用

sysHAX调度器原理剖析:智能决策算法如何实现资源最优利用

【免费下载链接】sysHAXsysHAX Heterogeneous collaborative acceleration runtime项目地址: https://gitcode.com/openeuler/sysHAX

前往项目官网免费下载:https://ar.openeuler.org/ar/

在异构计算环境中,如何让CPU、GPU等计算资源高效协同工作一直是技术难题。sysHAX作为一款Heterogeneous collaborative acceleration runtime(异构协同加速运行时),其核心调度器通过智能决策算法实现了计算资源的最优利用。本文将深入解析sysHAX调度器的工作原理,揭示其如何动态分配任务、平衡负载,最终提升系统整体性能。

调度器在系统架构中的核心地位

sysHAX采用分层架构设计,调度器(Scheduler)位于核心层,是实现资源智能分配的关键组件。从系统架构图可以清晰看到,调度器与Engine、MetricsService和SystemMonitor紧密协作,共同构成了系统的"大脑"。

图1:sysHAX系统架构,展示了调度器在整体系统中的位置和协作关系

调度器的核心职责包括:

  • 根据SystemMonitor提供的实时系统指标做出调度决策
  • 动态分配任务到CPU或GPU执行
  • 实现任务的负载均衡和资源优化
  • 提供设备和token限制的决策支持

调度器的实现代码位于src/core/scheduler.py,通过类Scheduler封装了所有调度逻辑。

智能决策算法:动态选择最优执行设备

sysHAX调度器的核心在于其智能决策算法,该算法能够根据系统实时状态动态选择任务的最佳执行设备。决策过程主要基于以下几个关键因素:

1. 设备负载状况检查

调度器首先检查GPU和CPU的当前负载情况:

  • 当GPU运行任务数为0时,优先将任务分配给GPU(调度码100)
  • 当CPU运行任务数为0且GPU已有任务时,优先分配给CPU(调度码200)
  • 当CPU任务数达到最大并发量时,自动切换到GPU(调度码101)

这些基础规则确保了在设备空闲时能够快速利用资源,避免资源浪费。

2. 吞吐量智能比较

调度器会持续监控GPU和CPU的吞吐量(tokens/s),并以此作为任务分配的重要依据。代码中通过以下方式计算吞吐量:

gpu_decode_throughout_per_batch = ( self.metrics_service.gpu_decode_throughout / self.metrics_service.gpu_running_num if self.metrics_service.gpu_running_num > 0 else 0) cpu_decode_throughout_per_batch = ( self.metrics_service.cpu_decode_throughout / self.metrics_service.cpu_running_num if self.metrics_service.cpu_running_num > 0 else 0)

当GPU吞吐量高于CPU时,优先选择GPU执行任务;反之则选择CPU,确保任务始终在效率最高的设备上运行。

3. 动态负载均衡策略

当系统刚启动或吞吐量数据不足时(小于0.1 tokens/s),调度器会采用动态试探策略,向GPU和CPU同时发送任务以收集性能数据。这种自适应机制使系统能够在各种环境下都能做出最优决策。

异构计算协同:CPU与GPU的无缝协作

sysHAX调度器特别优化了CPU与GPU的协同工作模式,实现了任务的智能拆分和协同执行。通过下图可以直观了解这一协作流程:

图2:CPU与GPU协同工作流程图,展示了任务在异构设备间的分配与协作

调度器实现了一种创新的任务拆分机制:

  • 将Prefill任务分配给GPU执行,利用GPU在并行计算上的优势
  • 将Decode任务分配给CPU执行,充分利用CPU在串行处理上的效率
  • 通过共享内存(Shared memory)实现KV Cache的高效传输与共享

这种分工模式充分发挥了不同计算设备的特性,大幅提升了整体系统性能。调度器会自动为任务添加num_decode_tokens参数,实现任务的智能拆分:

if self.syshax_config.auto_pd_offload and decision["device"] == "CPU": # 不含有num_decode_tokens字段,说明是完整任务,首先会进行prefill任务 # CPU侧不适合执行prefill任务,当开启auto_pd_offload会自动进行PD解耦 task_data["input"]["num_decode_tokens"] = 1 decision["device"] = "GPU" self.gpu_scheduled_running_num += 1

任务调度流程:从提交到执行的全生命周期管理

sysHAX调度器对任务的全生命周期进行精细化管理,确保每个任务都能得到最优处理。完整的调度流程包括以下几个关键步骤:

1. 任务提交与排队

任务通过submit_task方法提交到调度器,进入等待队列:

async def submit_task(self, data: dict[str, Any]) -> None: output_queue = asyncio.Queue() task_data = { "input": data, "output_queue": output_queue, "create_time": time.time() } await self.waiting.put(task_data) return output_queue

2. 调度决策与任务分配

调度器循环检查等待队列,对每个任务进行决策并分配到合适的设备:

async def scheduler(self) -> dict[str, int]: scheduled = {"GPU": 0, "CPU": 0, "skipped": 0} while not self.waiting.empty(): # 检查设备资源是否充足 if self.gpu_running_num >= self.gpu_max_batch and \ self.cpu_running_num >= self.cpu_max_batch: break # 获取任务并做出调度决策 task_data = self.waiting.get_nowait() decision = self._make_decision() # 根据决策分配任务到GPU或CPU执行 # ...

3. 任务执行与结果返回

任务分配后,由_execute_task方法负责在指定设备上执行,并通过输出队列返回结果:

async def _execute_task(self, device: str, task_data: dict[str, Any]) -> None: request = task_data["input"] output_queue = task_data["output_queue"] # 执行任务并返回结果 async for chunk in self.runner.task_handler(device=device, data=request): await output_queue.put(chunk) # ...

4. 资源释放与状态更新

任务执行完成后,调度器会更新设备资源状态,释放占用的资源:

finally: if device == "GPU": self.gpu_running_num -= 1 self.metrics_service.set_gpu_running_num(self.gpu_running_num) elif device == "CPU": self.cpu_running_num -= 1 self.metrics_service.set_cpu_running_num(self.cpu_running_num)

性能优化策略:实现资源利用最大化

sysHAX调度器内置了多种性能优化策略,确保系统资源得到最大化利用:

1. 批处理优化

调度器设置了CPU和GPU的最大批处理大小(默认为256),避免单个设备负载过重:

self.cpu_max_batch = 256 self.gpu_max_batch = 256

2. 实时监控与动态调整

调度器通过MetricsService持续监控系统性能指标,并根据实时数据动态调整调度策略。这种反馈机制使系统能够适应不断变化的工作负载。

3. 任务优先级管理

调度器会根据任务创建时间和类型进行优先级排序,确保关键任务得到优先处理。

4. 自动PD卸载

当开启auto_pd_offload功能时,调度器会自动将Prefill和Decode任务拆分到不同设备执行,充分发挥异构计算的优势。

调度决策可视化:直观了解资源分配逻辑

为了帮助开发者理解调度决策过程,sysHAX调度器定义了详细的调度码和日志消息。通过这些信息,可以清晰追踪每个任务的调度原因:

SCHEDULE_DICT: dict[int, Any] = { 100: "gpu_running_num为0,优先向GPU发任务", 101: "CPU分配的运行中请求数{cpu_allocated},超过最大并发量{cpu_max},优先向GPU发任务", 102: { "message": "{reason_detail}", "reasons": { "GPU_LOW_THROUGHPUT": "GPU、CPU暂时无法检测到吞吐量,动态向二者发送请求,本次向GPU发送请求", "GPU_HIGHER_TP": "GPU平均吞吐量{gpu_tp:.2f}tokens/s,高于CPU平均吞吐量{cpu_tp:.2f}tokens/s,优先向GPU发任务", }, }, # ... }

这些调度码和消息会通过日志系统输出,帮助开发者调试和优化调度策略。

总结:智能调度如何提升系统性能

sysHAX调度器通过以下几个方面实现了资源的最优利用:

  1. 全面的系统监控:实时收集CPU、GPU的负载和性能数据
  2. 智能决策算法:基于多因素动态选择最优执行设备
  3. 异构协同优化:充分发挥CPU和GPU的各自优势
  4. 精细化资源管理:合理分配任务,避免资源浪费
  5. 自适应调整机制:根据系统状态动态优化调度策略

通过这些技术手段,sysHAX调度器能够在复杂的异构计算环境中实现资源的最优配置,显著提升系统整体性能和响应速度。无论是在高性能计算场景还是在大规模并发服务中,sysHAX的智能调度算法都能为用户提供高效、稳定的计算服务。

要开始使用sysHAX,只需克隆仓库并按照部署指南操作:

git clone https://gitcode.com/openeuler/sysHAX

详细的部署指南可以参考以下文档:

  • CPU环境部署指南
  • CPU+GPU环境部署指南
  • CPU+NPU环境部署指南

【免费下载链接】sysHAXsysHAX Heterogeneous collaborative acceleration runtime项目地址: https://gitcode.com/openeuler/sysHAX

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