UE Turbo Build Shaders Controller 插件
主要目的是扩展UE的Shader编译器, 扩展到多机可以共享算力.
更新
2021-10-30 目前已经实现可用版本,正在测试效率,如果效率可以打算上架虚幻商城插件方便使用。
原理
- 扩展一个Controller 支持Shader 编译
- Shader编译线程消费Shader编译任务,启动一个Client进程来批量处理任务
- Client进程与编译器线程通过UDP Socket/NamedPipe通信获取编译结果发布到MQ
- 编译器接收到编译结果后,调用ShaderCompilerManager报告结果
- 分布式多机的Agent通过MQ拉取任务编译
Turbo Build Controller 插件
插件主要扩展消费编译任务(已经是批处理),参考XGE Controller插件
EnqueueTask 处理
接收到一个Batch 任务, 将通过Socket/NamedPipe方式发送到Client进程消费
FetchResult 线程
此线程等待读取Client进程的任务处理结果,将受到的任务报告给Manager (参考XGE Controller)
Client 进程
此进程主要使用Python编写用于快速验证可用原型, 主要用来分发任务TASK 。
Socket/NamedPipe 接受任务线程
从UE插件接受任务, 将任务转换为远程计算工作JOB, 本地独立线程处理或者提交给远程MQ(REDIS)
反馈结果线程
将从MQ读取结果并处理,然后发送给UE Socket/NamedPipe(任务ID), 通知UE检查结果
任务分发
可以本地执行或者远程执行,
- 接收到的任务按顺序分发给远程, 设置超时时间。
- 如果超时,则本地执行(由于DistributedShareCompilerThreadRunnable已经实现,可不做处理);
- 本地空闲状态也可消费,自主决定是否启动Agent进程;
任务包括: 任务工具集, 任务参数(输入,命令行模板)
任务结果 = 工具集(任务参数)
任务环境
任务环境表示任务需要执行准备的环境, 主要是依赖文件。
Client 在初始化时会声明
任务参数
主要是任务输入相关, 包含输入文件, 期望输出文件路径声明,执行命令等
任务分发中心(REDIS)
各个Agent 通过REDIS 获取任务, 执行结果并返回。
Client 上传的任务, Agent 消费的任务回写结果。
任务存储模型
- job_pending:
:list 任务使用List存储(ID,[INPUTS,OUTPUTS],CMD,TOOL_ENV,PATH_MAP) - job_finish:
:list 任务结果 - job_state:
: hash (key: code, stdout, stderr, outf:xx1, outf:xx2, inf:xx1, inf:xx2, cmd:xxx, tool_id:xxx, begin_time:xxxx, expired_time:xxxx) - toolset_ctx:hash , 主要是toolid 对应的smb 路径(确保所有client与agent可访问smb)
分发操作方法
Client任务提交
- Client启动时会初始化任务环境, 会在SMB上创建对应的层次目录, 将工具传输上去 .
并将工具id 在toolset_ctx 表中登记 : {id:path} - Client任务重启也会更新工具<包含引擎和Shader版本号>
- Client收到插件任务请求时, 构造一个job_state:
:task_id , 将任务参数填入其中 - 对于输入文件直接读取存入到REDIS中(假设都是小文件)
- 然后在task_pending:
中插入 task_id
- Client启动时会初始化任务环境, 会在SMB上创建对应的层次目录, 将工具传输上去 .
Agent 任务消费
- Agent 本地空闲时会启动N个进程从REDIS中获取任务;
- 取出任务时, 首先检查任务环境是否OK,如果没有则调用XCOPY将SMB的环境COPY到本地工作目录(临时目录)
- 检查任务参数的输入文件,保存到本地文件
- 设置环境信息,执行命令行程序
- 程序执行过程中可每10s更新一次结果(stdout,stderr), 将程序返回结果设置到 job_state中
- 最终程序完成时, 设置job_finish表
Client 任务获取结果
Client进程中会启动一个进程来缉拿查job_finish 列表, 从job_finish 中获取结果
每取出一个结果, 检查job_state 的数据,将job_state 的结果写入到文件中.
然后通过UDP Socket/NamedPipe发送给插件的编译器线程插件编译器线程获取结果
插件编译器线程从UDP Socket/NamedPipe中获取结果, 判断return code 和 输出, 根据情况显示或者报错等。
实现原型
- 先在插件中实现本地编译的方法.ok
- 实现Client进程本地编译.ok
- 实现插件与Client进程通信异步编译.ok
- 实现REDIS数据模型操作.ok
- 实现同机器REDIS通信Agent消费任务.ok
- 实现跨机器验证效率.ok
- 增加空闲监测和WEB监控显示.ok
- 效率优化.doing
