登录
注册
开源
企业版
高校版
搜索
帮助中心
使用条款
关于我们
开源
企业版
高校版
私有云
模力方舟
AI 队友
登录
注册
轻量养虾,开箱即用!低 Token + 稳定算力,Gitee & 模力方舟联合出品的 PocketClaw 正式开售!点击了解详情
代码拉取完成,页面将自动刷新
仓库状态说明
开源项目
>
人工智能
>
机器学习/深度学习
&&
捐赠
捐赠前请先登录
取消
前往登录
扫描微信二维码支付
取消
支付完成
支付提示
将跳转至支付宝完成支付
确定
取消
Watch
不关注
关注所有动态
仅关注版本发行动态
关注但不提醒动态
2.8K
Star
9.1K
Fork
5.3K
GVP
MindSpore
/
mindspore
关闭
代码
Issues
220
Pull Requests
283
Wiki
统计
流水线
服务
质量分析
Jenkins for Gitee
腾讯云托管
腾讯云 Serverless
悬镜安全
阿里云 SAE
Codeblitz
SBOM
我知道了,不再自动展开
更新失败,请稍后重试!
移除标识
内容风险标识
本任务被
标识为内容中包含有代码安全 Bug 、隐私泄露等敏感信息,仓库外成员不可访问
[RFC]: 多核并行
DONE
#ICYDMX
guangpengz
成员
创建于
2025-09-17 11:05
## 背景与目标描述. ### 1 背景与挑战 随着AI技术的快速发展,神经网络模型的参数量及训练数据规模均呈现指数级增长。当前主流大模型的参数规模已远超单张加速卡的内存容量,必须依赖模型切分与多设备分布式训练,目前分布式训练主要手段包括数据并行、流水线并行、模型并行、专家并行、序列并行等。分布式训练技术虽然能够支撑DeepSeek MoE 模型671B满血参数模型训练,但是MFU普遍在40%左右,仍有较大提升空间。主要存在以下问题: #### 计算的有效算力利用率较低  DeepSeekV3的Cube算子的平均mac利用率为67%(端到端占比54%,大部分Cube算子占用核数资源“过剩”、利用率不足),存在较大提升空间(目标90%+);未掩盖Vector算子占比高(端到端占比18%,未掩盖Vector算子执行期间Cube核算力浪费) #### 通信掩盖比例不足  DeepSeekV3的EP通信占比17%(掩盖比例61%,未掩盖通信执行期间Cube核算力浪费),存在较大提升空间(目标90%+);近期Kimi-K2的1T MOE直接采用了DeepSeekV3架构,通过进一步扩展专家数256→384来提升参数量到万亿,对EP通信开销提出更大的挑战 类DeepSeek MoE模型除有效算力利用率低和通信掩盖比例不足外,还有负载不均问题,主要以MoE为例: #### MoE训练专家负载不均挑战  MoE负载不均,表现在不同卡专家计算与通信不均衡,进而导致端到端性能下降。 ### 2 目标 针对算子有效算力利用率低、掩盖比例不足、MoE训练专家负载不均等问题,结合AI框架当前的分布式并行能力。我们提出idea,使能AI框架提供多核并行编程和多核并行调度基础能力,让卡级并行和核级并行(A3每卡有24~25个核)做并行协同,充分使能昇腾算力。 具体来说,AI框架提供多核并行编程和多核并行调度基础能力,支持CANN/DVM/Triton多算子分核控制与混合使用,主要包括: - 多流并发:提供计算多流并发能力,支持脚本侧控制并发算子 - 多核执行序调整:通过Event.record和Event.wait支持手动调整执行序,精准控制并发算子执行 - 算子分核:支持进程级和线程级算子控核能力,在结合多流并发和执行序调整共同作用下,最大化算力利用率  用户在Python侧编程,可灵活、快速地实现卡、核并行分核协同调度,实现大范围并发、高密流水&掩盖等,达到性能极致优化。基于上述多核并行编程能力,实现DeepSeek MoE细粒度多核并行&MoE专家负载均衡。 ### 3 分核实验 针对多核并行技术手段主要思想,对多核并行的可行性、效果进行了实验穿刺,主要包括单算子分核实验和CV/CC算子并发实验。 #### 单算子分核实验 基于DeepSeekV3中出现频率较高的算子,进行单算子分核实验,主要验证核数对算子性能的影响,具体实验结果如下图。 各shape下单算子性能受核数影响:  BMM不同核数下的MAC利用率:  由以上实验结果: (1)DeepSeekV3中典型算子性能在分核场景下呈非线性下降趋势,大部分shape下使用一半核就能达到最优性能。 (2)核数越多,MAC利用率呈下降趋势,机器未被充分利用。 因此,针对算子分核策略的调优可以在不降低性能的情况下释放更多算子资源,以完成其他可并行计算/通信。 #### CV/CC算子并发实验 Cube Vector并发:  MatMul和Mul算子并发,有约12%收益。 Cube Cube并发: 下图为FA和MatMul并发效果  下图为MatMul并发效果  由以上实验结果: 在并行计算/通信时,合理控制核数,可提高端到端性能。 ## 建议的方案. ### 1 基础能力接口详细设计 为提供多核并行编程模型,需要具备多核并发能力,细化子能力包括计算分流、执行序控制、分核。 #### 1.1 计算分流接口 ##### 接口设计 MindSpore计算分流接口,使用with使能分流,代码写法如下: ``` s1=ms.runtime.Stream() class XXX: ... def construct(self, args): a = Tensor(np.ones([1024, 2048]), ms.float32) b = Tensor(np.ones([2048, 4096]), ms.float32) c1 = ops.matmul(a, b) with ms.runtime.MyMsJitStreamCtx(s1): c = ops.matmul(a,b) ms.runtime.synchronize() ``` 静态图分流接口流程:  目前计算流标签设计举例如下: key:stream_id value: 0 ##### 需求拆解: 前端:分流的前端实现,支持with写法进行多流调用。预期时间:1030 后端(#ID1FGR):分流的后端实现,基于with表达,Stream有唯一ID,后端按照stream_id对算子打属性,及后端按照属性设置对应流运行。预期时间:1030 后端融合pass:不同流的算子,不能进行后端pass融合,需要梳理具体涉及的pass,并进行逻辑判断优化不融合不同流算子。预期时间:1030 DVM:不同流的算子,不能进行DVM算子融合,需要有具体影响分析及方案,并开发不融合不同流算子。预期时间:待定 #### 1.2 执行序控制接口 ##### 接口设计 MindSpore静态图目前支持depend控制算子下发序,在计算单流时,等同于控制执行序,但是在多流情况下,depend表达能力不足,无法在多流间控制算子的执行序。动态图支持通过Event对象或Stream对象来控制算子执行序,其中涉及到的接口如下: ``` mindspore.runtime.Event Event elapsed_time: 返回记录事件之后到记录end_event之前所用的时间(以毫秒为单位) query: 检查事件当前捕获的所有工作是否已完成 record: 在给定的流中记录事件 synchronize:等待直到完成当前此事件捕获的所有工作 wait:使提交给给定流的所有未来工作等待此事件 ``` ``` mindspore.runtime.Stream Stream query: 检查所有提交的工作是否已完成 record_event: 记录一个事件 synchronize: 等待此流中的所有算子执行完成 wait_event:使提交到流的所有未来工作等待本事件 wait_stream:所有提交到本流的未来工作都将等待,直到所有算子都提交至给定流并执行完成 ``` 通过以上接口可以组合实现多流间控制。针对Event对象,编码格式及效果如下:  ``` depend = ops.Depend() s1=ms.runtime.Stream() s2=ms.runtime.Stream() event1=ms.runtime.Event() event2=ms.runtime.Event() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, a1) r2 = ops.matmul(b1, b1) event1=depend(event1, r1) event1=depend(event1, r2) event1.record() with ms.runtime.MyMsJitStreamCtx(s2): event1.wait() a2=depend(a2, event1) b2=depend(b2, event1) r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2=depend(event2,r3) event2=depend(event2,r4) event2.record() ``` Event对象,进阶编码格式如下: ``` s1=ms.runtime.Stream() s2=ms.runtime.Stream() event1=ms.runtime.Event() event2=ms.runtime.Event() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, b1) r2 = ops.matmul(b1, b1) event1.record() with ms.runtime.MyMsJitStreamCtx(s2): event1.wait() r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2.record() ``` 以上主要区别为,进阶编码格式无需用户手动添加depend算子。 针对Stream对象,考虑在无需用户手动添加depend算子后,进行补充支持wait和event方法,最终编码格式如下: ``` depend = ops.Depend() s1=ms.runtime.Stream() s2=ms.runtime.Stream() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, b1) r2 = ops.matmul(b1, b1) event1 = s1.record_event() with ms.runtime.MyMsJitStreamCtx(s2): s2.wait_event(event1) r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2 = s2.record_event() ``` ##### 需求拆解 前端:执行序控制的前端实现,包括新增脚本侧event类型,能够入图,新增event.record()和event.wait()相关接口,同时能在入图时自动添加event入参和出参,保证用户能够通过depend来进行流内执行序控制,流间执行序控制直接通过event控制。预期时间:1030 后端:执行序控制的后端实现,新增event.record()和event.wait()相关接口,后端+运行时的处理机制,record、wait 在后端的实现,stream属性在运行时的解析处理。预期时间:1030 #### 1.3 分核接口 ##### 接口设计 CANN底层能力提供控核能力支持接口。接口主要分为进程级控核和线程级控核,参考CANN接口的设计,进行了MindSpore对外接口规范设计,如下: | | CANN接口 | 入参 | 备注 | MindSpore暴露接口 | |---|--------|----|----|---------------| | 进程级控核 | aclError aclrtSetDeviceResLimit(int32 deviceId, enum type, uint32_t value) | // type 0:AIC; 1: AIV | 开启device粒度资源分配,为device设置各加速器的数量 | ms.runtime.set_device_limit(device, cube_num=-1, vector_num=-1) | | 进程级控核 | aclError aclrtResetDeviceResLimit(int32 deviceId) | | 关闭device粒度资源分配功能 | | | 进程级控核 | aclError aclrtGetDeviceResLimit(int32 deviceId, enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 获取device正在使用的资源分配。 | ms.runtime.get_device_limit(device) | | 线程级控核 | aclError aclrtSetStreamResLimit(aclrtStream stream, enum type, uint32_t value) | // type 0:AIC; 1: AIV | 开启stream粒度资源分配,为stream设置各加速器的数量 如果没有setLimit,则使用platform里原有的芯片规格 | ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1) / with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) | | 线程级控核 | aclError aclrtResetStreamResLimit(aclrtStream stream) | | 关闭stream粒度资源分配功能 调用aclrtSetStreamResLimit接口设置指定Stream的Device资源限制后,可调用本接口重置指定Stream的Device资源限制,恢复默认配置,此时可通过aclrtGetStreamResLimit接口查询默认的资源限制。 | ms.runtime.reset_stream_limit(stream) | | 线程级控核 | aclError aclrtGetStreamResLimit(aclrtStream stream, enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 查询stream对应的资源分配信息 | ms.runtime.get_stream_limit(stream) | | 线程级控核 | aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) | | 线程变量streamLimitflag=true 设置本线程后续使用stream粒度资源分配,仅保存线程变量,不允许回调其它模块 (aclrtUseStreamResInCurrentThread是专门为aclnn算子设计,aclnn算子tiling时获取不到stream信息,而核是绑定到stream上,因此逃生通道给aclnn能获取到具体的Stream级别核数) | | | 线程级控核 | aclError aclrtUnuseStreamResInCurrentThread() | | 在本线程不使用stream粒度资源分配功能,回退使用进程粒度资源分配或最原始的配置 线程变量streamLimitflag=false; 在当前线程中取消使用指定Stream上的Device资源限制。 (pta未真正使用该接口:①用户在该线程切换stream,会重新调用use接口 ②用户线程不切换,则也无需unuse) | | | 线程级控核 | aclError aclrtGetResInCurrentThread(enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 获取本线程正在使用的资源分配。按照stream级>进程级>soc级的顺序返回value | | 基于CANN提供的进程级控核接口,实现的进程级控核代码示例如下: ``` # 设置当前device的核数策略, 其中cube核数使用12个, vector核数使用24个 # 底层调用CANN接口 aclError aclrtSetDeviceResLimit(int32 deviceId, enum type, uint32_t value) ms.set_device_limit(torch.npu.current_device(), cube_num=12, vector_num=24) # 查询当前device的核数策略,返回dict:{'cube_core_num': 12, 'vector_core_num': 24} # 底层调用CANN接口 aclError aclrtGetDeviceResLimit(int32 deviceId, enum type, uint32_t *value) ms.get_device_limit(ms.runtime.current_device()) ``` 线程级控核需要在代码中多次调用,以控制单算子核数。MindSpore动态图模式支持以上五个接口,考虑到图模式有图编译阶段,线程级控核接口若入图,需要封装为内部算子提供;同时,线程级控核接口ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)的对象入参为stream,为了图编译后执行保序,需要用户添加depend算子,而且需要set_stream_limit有返回值给到depend入参,对用户来说不易理解;在控核范围方面,也考虑到set_stream_limit接口的生效范围不易读。因此,我们使用with语句代替ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)提供线程级控核。 with语句写法如下: ``` with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) ``` 具体代码示例如下: ``` import mindspore as ms x = Tensor(np.ones([1024, 1024]), ms.float32) stream1 = ms.runtime.current_stream() stream2 = ms.runtime.Stream() event1 = ms.runtime.Stream() event2 = ms.runtime.Stream() depend = ops.Depend() def construct(self, args): # 第一个算子调用前,需要runtime自动调用CANN接口绑定流stream1: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.StreamLimitCtx(stream1, cube_num=3, vector_num=8): output = ops.add(x, x) # cube:3 vector:8 output = ops.add(output, x) # cube:3 vector:8 event1 = depend(event1, output) event1.record() # 切换流,runtime需要自动调用CANN接口更新绑定流stream2: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.MyMsJitStreamCtx(stream2): event1.wait() x = depend(x, event1) output = ops.add(x, output) # 用满核 with ms.runtime.StreamLimitCtx(stream2, cube_num=6, vector_num=10): output = ops.add(x, output) # cube:6 vector:10 with ms.runtime.StreamLimitCtx(stream2, cube_num=3, vector_num=8): output = ops.add(x, output) # cube:3 vector:8 # 切换流,runtime需要自动调用CANN接口更新绑定流stream1: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.StreamLimitCtx(stream1, cube_num=5, vector_num=6): output = ops.add(x, output) # cube:5 vector:6 output = ops.add(x, output) # 用满核 # tiling hash_key需要做优化:(op_type,input_shape,input_type)->(op_type,input_shape,input_type,cube_num,vector_num)。通过调用接口aclError aclrtGetResInCurrentThread(enum type, uint32_t *value)实时获取cube_num和vector_num ``` 以上代码展示控核接口的调用,对应acl接口调用,由于版本问题,需要使用dopen调用,防止由于版本问题编译不通过。同时需要runtime记录每次算子调用使用的Stream,如果出现Stream切换,需要重新调用aclError aclrtUseStreamResInCurrentThread(aclrtStream stream)接口将Stream绑定到当前线程。 线程级控核接口set_stream_limit可以在执行期间多次调用,将分核策略绑定到对应的stream上,后续在对应Stream运行的算子将采纳最近一次绑定的分核策略。 ##### 需求拆解 后端(#ID1FLX):后端提供分核控制接口,可以供用户调用(共5个接口);runtime运行时管理,能够调用CANN对应接口实现device级别和stream级别控核。预期时间:1030 算子cache(https://gitee.com/mindspore/mindspore/issues/ICXUJ3):aclnn算子调用支持分核后,框架侧需要对算子调用的tiling进行缓存变更,由以往根据shape+type+op_type生成的hashkey,变更为由shape+type+op_type+cube_num+vector_num生成hashkey。预期时间:1030 DVM:可以通过接入CANN接口对aclnn分核同样的调用形式,来实现DVM算子控核。预期时间:1030 ### 2 收益场景 #### 2.1 MoE多副本-多核并行,实现大范围并发、高密流水&掩盖 AS IS: 现状:1)Cube利用率不足 & Vector占比高;2)EP All2All通信开销大且引入断流开销,专家负载不均时开销进一步加剧  TO BE: 多核并行- 基于多副本并行(token维切片),每个副本切片独立计算流,多核并发实现高密流水,同时达成大范围并发&掩盖: 1)切片后单个切片计算量降低,通过对分片的计算&通信做分核并发和执行序编排(Cube-Cube并发、Cube-Vector并发、通算并发)冲高算力利用率,支持细粒度切片、提升流水掩盖率; 2)单边通信替换集合通信,消除非必要同步,单副本切片load完自己所需数据即可启动后续计算、无需等待其他卡,消除断流开销; 3)单边通信算子需要占用少量Vector核资源(实测DeepSeek模型典型场景单边通信4~8核为最优分核策略),用户可结合单边通信的分核接口进一步提升通算并发效率,提升流水密度  #### 2.2 核级负载均衡  针对MOE训练专家负载不均挑战: - AS IS: 不同卡专家计算与通信不均衡,端到端性能下降 - TO BE: 热点计算任务做切片,分配到非热点节点,多核并行掩盖Load/Store开销,端到端性能提升30%~50% ## 测试设计和测试计划. | MindSpore对用户暴露接口 | 类型 | 功能 | 支持模式 | 功能详解 | |--------------------------------------------------------------------|-------|-------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------| | with ms.runtime.MyMsJitStreamCtx(s1) | 分流 | 图模式下支持多流 | 图模式,支持入图 | | | Event.record() | 执行序控制 | 发送信号,等待wait | 图模式,支持入图 | | | Event.wait() | 执行序控制 | 等待record信号 | 图模式,支持入图 | | | ms.set_device_limit(device, cube_num=-1, vector_num=-1) | 分核 | 进程级控核设置接口 | 动态图模式 | 开启device粒度资源分配,为device设置各加速器的数量。 | | ms.get_device_limit(device) | 分核 | 进程级控核查询接口 | 动态图模式 | 获取device正在使用的资源分配。 | | ms.set_stream_limit(stream, cube_num=-1, vector_num=-1) | 分核 | 线程级控核设置接口 | 动态图模式 | 开启stream粒度资源分配,为stream设置各加速器的数量。如果没有setLimit,则使用platform里原有的芯片规格 | | ms.reset_stream_limit(stream) | 分核 | 线程级控核重置接口 | 动态图模式 | 关闭stream粒度资源分配功能。调用aclrtSetStreamResLimit接口设置指定Stream的Device资源限制后,可调用本接口重置指定Stream的Device资源限制,恢复默认配置,此时可通过aclrtGetStreamResLimit接口查询默认的资源限制。 | | ms.get_stream_limit(stream) | 分核 | 线程级控核查询接口 | 动态图模式 | 查询stream对应的资源分配信息 | | with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) | 分核 | 线程级控核设置接口 | 图模式,支持入图 | 开启stream粒度资源分配,为stream设置各加速器的数量。如果没有setLimit,则使用platform里原有的芯片规格 | 结合多流、执行序、分核,主要通过构造以下场景进行测试验证,不开启DVM自动融合,支持aclnn算子分核。 多流: 1、双流单算子:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,其中Matmul算子运行在主S1,Add算子运行在S2,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期Matmul算子和Add算子可以并发执行,即存在执行时间重叠。 2、双流多算子:构建网络结构,使用多个Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,其中主流运行多个Matmul/Add算子,其余流也运行多个Matmul/Add算子,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期两个流的算子可以并发执行,即存在执行时间重叠。 3、多流多算子:构建网络结构,使用多个Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,其中Matmul算子运行在主流,MatMul/Add算子运行在其余流,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期多流的算子可以并发执行,即存在执行时间重叠。注意,由于hostbound,可以在每个流最开始执行一个超大shape算子用例,减小hostbound,让其正常并发。 执行序: 1、单event单record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,若直接执行,预期Matmul和Add存在时间并发,在S1执行Matmul后插入Event.record(),在S2的Add算子执行前插入Event.wait(),可以让Matmul和Add不存在并发,即控制两者的执行时间,不存在时间重叠。 2、多event多record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,若直接执行,预期每个流的算子均存在时间并发重叠,若创建5个event,重复在每个流执行前插入Event.wait(),并在每个流的最后插入Event.record(),控制每个流的算子执行时机,可以让算子执行不存在时间重叠。 3、单event对应多record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,可以在主流执行Event.record(),在其余分流的开始执行同一个Event对象的Event.wait(),预期可以控制S2、S3、S4、S5的算子并发,并且均在S1之后执行。 分核: 1、动态图测试device控核:在单流时,使用ms.runtime.set_device_limit(device, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_device_limit(device)的返回值能够对应,单流算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 2、动态图测试Stream控核-单次调用:在单流时,使用ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_stream_limit(device)的返回值能够对应,单流算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 3、动态图测试Stream控核-多次调用:在单流时,使用ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)控制核数,使用多个算子,例如matmul,在每个算子调用之间插入set_stream_limit,且配置不同核数,预期算子的核数使用和最近一次配置一致;在使用reset_stream_limit后,后面算子的运行使用核数和不配置Stream分核时一致。 4、静态图测试Stream控核-单次调用:在单流时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_stream_limit(device)的返回值能够对应,with作用域内算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 5、静态图测试Stream控核-多次调用:在单流时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制核数,使用多个算子,例如matmul,在每个算子调用之间插入StreamLimitCtx,且配置不同核数,with作用域内算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致,作用域外使用默认核数。 多流、执行序、多核交叉验证: 1、动态图测试多核并行-功能验证:使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发,并通过Event.record和Event.wait控制算子的执行序,例如让流1的Matmul和流2的Add算子并发,同时,使用ms.runtime.set_stream_limit(device, cube_num=-1, vector_num=-1)控制MatMul算子和Add算子的核数,例如让Matmul的cube_num为24,同时让Add算子的vector_num为20,预期可以正常并发执行,且流1的Matmul和流2的Add的执行核数和预期一致。 2、静态图测试多核并行-功能验证:使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发,并通过Event.record和Event.wait控制算子的执行序,例如让流1的Matmul和流2的Add算子并发,同时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制MatMul算子和Add算子的核数,例如让Matmul的cube_num为24,同时让Add算子的vector_num为20,预期可以正常并发执行,且流1的Matmul和流2的Add的执行核数和预期一致。 3、算子PASS优化验证:构造一个继承PatternProcessPass基类的pass(MatmulAssignaddFusion)结构,融合前节点都不带stream_id或core_num属性,预期可以融合且融合后节点不带stream_id或core_num属性;使用分流将算子分散在不同流,预期不会融合;使用分核接口将算子的核数设置为不同值,预期不会融合。 4、算子Cache优化验证:构造多核并行代码,使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发。在流内使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制算子执行核数,且对同一算子多次执行(不改变输入shape和算子),而且每次配置的核数一致,可以开启INFO日志观察,预期算子执行时Cache的hash_id一致。 ## 期望的反馈时间. ## CC List. 前端: @ginfung 、 @Margaret_wangrui 、@Qiao_Fu 后端: @zpac 、 @zhangyinxia DVM:@gaoxiong1 算子调用Cache: @hbhu_bin 后端融合pass相关优化:@yuchaojie ## 其他补充信息. ## Before submitting a new issue... - [x] Make sure you already searched for previous [RFCs](https://gitee.com/mindspore/mindspore/issues?q=is%3Aall+label%3ARFC+sort%3Arecently-updated).
## 背景与目标描述. ### 1 背景与挑战 随着AI技术的快速发展,神经网络模型的参数量及训练数据规模均呈现指数级增长。当前主流大模型的参数规模已远超单张加速卡的内存容量,必须依赖模型切分与多设备分布式训练,目前分布式训练主要手段包括数据并行、流水线并行、模型并行、专家并行、序列并行等。分布式训练技术虽然能够支撑DeepSeek MoE 模型671B满血参数模型训练,但是MFU普遍在40%左右,仍有较大提升空间。主要存在以下问题: #### 计算的有效算力利用率较低  DeepSeekV3的Cube算子的平均mac利用率为67%(端到端占比54%,大部分Cube算子占用核数资源“过剩”、利用率不足),存在较大提升空间(目标90%+);未掩盖Vector算子占比高(端到端占比18%,未掩盖Vector算子执行期间Cube核算力浪费) #### 通信掩盖比例不足  DeepSeekV3的EP通信占比17%(掩盖比例61%,未掩盖通信执行期间Cube核算力浪费),存在较大提升空间(目标90%+);近期Kimi-K2的1T MOE直接采用了DeepSeekV3架构,通过进一步扩展专家数256→384来提升参数量到万亿,对EP通信开销提出更大的挑战 类DeepSeek MoE模型除有效算力利用率低和通信掩盖比例不足外,还有负载不均问题,主要以MoE为例: #### MoE训练专家负载不均挑战  MoE负载不均,表现在不同卡专家计算与通信不均衡,进而导致端到端性能下降。 ### 2 目标 针对算子有效算力利用率低、掩盖比例不足、MoE训练专家负载不均等问题,结合AI框架当前的分布式并行能力。我们提出idea,使能AI框架提供多核并行编程和多核并行调度基础能力,让卡级并行和核级并行(A3每卡有24~25个核)做并行协同,充分使能昇腾算力。 具体来说,AI框架提供多核并行编程和多核并行调度基础能力,支持CANN/DVM/Triton多算子分核控制与混合使用,主要包括: - 多流并发:提供计算多流并发能力,支持脚本侧控制并发算子 - 多核执行序调整:通过Event.record和Event.wait支持手动调整执行序,精准控制并发算子执行 - 算子分核:支持进程级和线程级算子控核能力,在结合多流并发和执行序调整共同作用下,最大化算力利用率  用户在Python侧编程,可灵活、快速地实现卡、核并行分核协同调度,实现大范围并发、高密流水&掩盖等,达到性能极致优化。基于上述多核并行编程能力,实现DeepSeek MoE细粒度多核并行&MoE专家负载均衡。 ### 3 分核实验 针对多核并行技术手段主要思想,对多核并行的可行性、效果进行了实验穿刺,主要包括单算子分核实验和CV/CC算子并发实验。 #### 单算子分核实验 基于DeepSeekV3中出现频率较高的算子,进行单算子分核实验,主要验证核数对算子性能的影响,具体实验结果如下图。 各shape下单算子性能受核数影响:  BMM不同核数下的MAC利用率:  由以上实验结果: (1)DeepSeekV3中典型算子性能在分核场景下呈非线性下降趋势,大部分shape下使用一半核就能达到最优性能。 (2)核数越多,MAC利用率呈下降趋势,机器未被充分利用。 因此,针对算子分核策略的调优可以在不降低性能的情况下释放更多算子资源,以完成其他可并行计算/通信。 #### CV/CC算子并发实验 Cube Vector并发:  MatMul和Mul算子并发,有约12%收益。 Cube Cube并发: 下图为FA和MatMul并发效果  下图为MatMul并发效果  由以上实验结果: 在并行计算/通信时,合理控制核数,可提高端到端性能。 ## 建议的方案. ### 1 基础能力接口详细设计 为提供多核并行编程模型,需要具备多核并发能力,细化子能力包括计算分流、执行序控制、分核。 #### 1.1 计算分流接口 ##### 接口设计 MindSpore计算分流接口,使用with使能分流,代码写法如下: ``` s1=ms.runtime.Stream() class XXX: ... def construct(self, args): a = Tensor(np.ones([1024, 2048]), ms.float32) b = Tensor(np.ones([2048, 4096]), ms.float32) c1 = ops.matmul(a, b) with ms.runtime.MyMsJitStreamCtx(s1): c = ops.matmul(a,b) ms.runtime.synchronize() ``` 静态图分流接口流程:  目前计算流标签设计举例如下: key:stream_id value: 0 ##### 需求拆解: 前端:分流的前端实现,支持with写法进行多流调用。预期时间:1030 后端(#ID1FGR):分流的后端实现,基于with表达,Stream有唯一ID,后端按照stream_id对算子打属性,及后端按照属性设置对应流运行。预期时间:1030 后端融合pass:不同流的算子,不能进行后端pass融合,需要梳理具体涉及的pass,并进行逻辑判断优化不融合不同流算子。预期时间:1030 DVM:不同流的算子,不能进行DVM算子融合,需要有具体影响分析及方案,并开发不融合不同流算子。预期时间:待定 #### 1.2 执行序控制接口 ##### 接口设计 MindSpore静态图目前支持depend控制算子下发序,在计算单流时,等同于控制执行序,但是在多流情况下,depend表达能力不足,无法在多流间控制算子的执行序。动态图支持通过Event对象或Stream对象来控制算子执行序,其中涉及到的接口如下: ``` mindspore.runtime.Event Event elapsed_time: 返回记录事件之后到记录end_event之前所用的时间(以毫秒为单位) query: 检查事件当前捕获的所有工作是否已完成 record: 在给定的流中记录事件 synchronize:等待直到完成当前此事件捕获的所有工作 wait:使提交给给定流的所有未来工作等待此事件 ``` ``` mindspore.runtime.Stream Stream query: 检查所有提交的工作是否已完成 record_event: 记录一个事件 synchronize: 等待此流中的所有算子执行完成 wait_event:使提交到流的所有未来工作等待本事件 wait_stream:所有提交到本流的未来工作都将等待,直到所有算子都提交至给定流并执行完成 ``` 通过以上接口可以组合实现多流间控制。针对Event对象,编码格式及效果如下:  ``` depend = ops.Depend() s1=ms.runtime.Stream() s2=ms.runtime.Stream() event1=ms.runtime.Event() event2=ms.runtime.Event() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, a1) r2 = ops.matmul(b1, b1) event1=depend(event1, r1) event1=depend(event1, r2) event1.record() with ms.runtime.MyMsJitStreamCtx(s2): event1.wait() a2=depend(a2, event1) b2=depend(b2, event1) r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2=depend(event2,r3) event2=depend(event2,r4) event2.record() ``` Event对象,进阶编码格式如下: ``` s1=ms.runtime.Stream() s2=ms.runtime.Stream() event1=ms.runtime.Event() event2=ms.runtime.Event() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, b1) r2 = ops.matmul(b1, b1) event1.record() with ms.runtime.MyMsJitStreamCtx(s2): event1.wait() r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2.record() ``` 以上主要区别为,进阶编码格式无需用户手动添加depend算子。 针对Stream对象,考虑在无需用户手动添加depend算子后,进行补充支持wait和event方法,最终编码格式如下: ``` depend = ops.Depend() s1=ms.runtime.Stream() s2=ms.runtime.Stream() def construct(self, args) with ms.runtime.MyMsJitStreamCtx(s1): r1 = ops.matmul(a1, b1) r2 = ops.matmul(b1, b1) event1 = s1.record_event() with ms.runtime.MyMsJitStreamCtx(s2): s2.wait_event(event1) r3 = ops.add(a2, b2) r4 = ops.add(b2, b2) event2 = s2.record_event() ``` ##### 需求拆解 前端:执行序控制的前端实现,包括新增脚本侧event类型,能够入图,新增event.record()和event.wait()相关接口,同时能在入图时自动添加event入参和出参,保证用户能够通过depend来进行流内执行序控制,流间执行序控制直接通过event控制。预期时间:1030 后端:执行序控制的后端实现,新增event.record()和event.wait()相关接口,后端+运行时的处理机制,record、wait 在后端的实现,stream属性在运行时的解析处理。预期时间:1030 #### 1.3 分核接口 ##### 接口设计 CANN底层能力提供控核能力支持接口。接口主要分为进程级控核和线程级控核,参考CANN接口的设计,进行了MindSpore对外接口规范设计,如下: | | CANN接口 | 入参 | 备注 | MindSpore暴露接口 | |---|--------|----|----|---------------| | 进程级控核 | aclError aclrtSetDeviceResLimit(int32 deviceId, enum type, uint32_t value) | // type 0:AIC; 1: AIV | 开启device粒度资源分配,为device设置各加速器的数量 | ms.runtime.set_device_limit(device, cube_num=-1, vector_num=-1) | | 进程级控核 | aclError aclrtResetDeviceResLimit(int32 deviceId) | | 关闭device粒度资源分配功能 | | | 进程级控核 | aclError aclrtGetDeviceResLimit(int32 deviceId, enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 获取device正在使用的资源分配。 | ms.runtime.get_device_limit(device) | | 线程级控核 | aclError aclrtSetStreamResLimit(aclrtStream stream, enum type, uint32_t value) | // type 0:AIC; 1: AIV | 开启stream粒度资源分配,为stream设置各加速器的数量 如果没有setLimit,则使用platform里原有的芯片规格 | ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1) / with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) | | 线程级控核 | aclError aclrtResetStreamResLimit(aclrtStream stream) | | 关闭stream粒度资源分配功能 调用aclrtSetStreamResLimit接口设置指定Stream的Device资源限制后,可调用本接口重置指定Stream的Device资源限制,恢复默认配置,此时可通过aclrtGetStreamResLimit接口查询默认的资源限制。 | ms.runtime.reset_stream_limit(stream) | | 线程级控核 | aclError aclrtGetStreamResLimit(aclrtStream stream, enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 查询stream对应的资源分配信息 | ms.runtime.get_stream_limit(stream) | | 线程级控核 | aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) | | 线程变量streamLimitflag=true 设置本线程后续使用stream粒度资源分配,仅保存线程变量,不允许回调其它模块 (aclrtUseStreamResInCurrentThread是专门为aclnn算子设计,aclnn算子tiling时获取不到stream信息,而核是绑定到stream上,因此逃生通道给aclnn能获取到具体的Stream级别核数) | | | 线程级控核 | aclError aclrtUnuseStreamResInCurrentThread() | | 在本线程不使用stream粒度资源分配功能,回退使用进程粒度资源分配或最原始的配置 线程变量streamLimitflag=false; 在当前线程中取消使用指定Stream上的Device资源限制。 (pta未真正使用该接口:①用户在该线程切换stream,会重新调用use接口 ②用户线程不切换,则也无需unuse) | | | 线程级控核 | aclError aclrtGetResInCurrentThread(enum type, uint32_t *value) | // type 0:AIC; 1: AIV | 获取本线程正在使用的资源分配。按照stream级>进程级>soc级的顺序返回value | | 基于CANN提供的进程级控核接口,实现的进程级控核代码示例如下: ``` # 设置当前device的核数策略, 其中cube核数使用12个, vector核数使用24个 # 底层调用CANN接口 aclError aclrtSetDeviceResLimit(int32 deviceId, enum type, uint32_t value) ms.set_device_limit(torch.npu.current_device(), cube_num=12, vector_num=24) # 查询当前device的核数策略,返回dict:{'cube_core_num': 12, 'vector_core_num': 24} # 底层调用CANN接口 aclError aclrtGetDeviceResLimit(int32 deviceId, enum type, uint32_t *value) ms.get_device_limit(ms.runtime.current_device()) ``` 线程级控核需要在代码中多次调用,以控制单算子核数。MindSpore动态图模式支持以上五个接口,考虑到图模式有图编译阶段,线程级控核接口若入图,需要封装为内部算子提供;同时,线程级控核接口ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)的对象入参为stream,为了图编译后执行保序,需要用户添加depend算子,而且需要set_stream_limit有返回值给到depend入参,对用户来说不易理解;在控核范围方面,也考虑到set_stream_limit接口的生效范围不易读。因此,我们使用with语句代替ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)提供线程级控核。 with语句写法如下: ``` with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) ``` 具体代码示例如下: ``` import mindspore as ms x = Tensor(np.ones([1024, 1024]), ms.float32) stream1 = ms.runtime.current_stream() stream2 = ms.runtime.Stream() event1 = ms.runtime.Stream() event2 = ms.runtime.Stream() depend = ops.Depend() def construct(self, args): # 第一个算子调用前,需要runtime自动调用CANN接口绑定流stream1: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.StreamLimitCtx(stream1, cube_num=3, vector_num=8): output = ops.add(x, x) # cube:3 vector:8 output = ops.add(output, x) # cube:3 vector:8 event1 = depend(event1, output) event1.record() # 切换流,runtime需要自动调用CANN接口更新绑定流stream2: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.MyMsJitStreamCtx(stream2): event1.wait() x = depend(x, event1) output = ops.add(x, output) # 用满核 with ms.runtime.StreamLimitCtx(stream2, cube_num=6, vector_num=10): output = ops.add(x, output) # cube:6 vector:10 with ms.runtime.StreamLimitCtx(stream2, cube_num=3, vector_num=8): output = ops.add(x, output) # cube:3 vector:8 # 切换流,runtime需要自动调用CANN接口更新绑定流stream1: # aclError aclrtUseStreamResInCurrentThread(aclrtStream stream) with ms.runtime.StreamLimitCtx(stream1, cube_num=5, vector_num=6): output = ops.add(x, output) # cube:5 vector:6 output = ops.add(x, output) # 用满核 # tiling hash_key需要做优化:(op_type,input_shape,input_type)->(op_type,input_shape,input_type,cube_num,vector_num)。通过调用接口aclError aclrtGetResInCurrentThread(enum type, uint32_t *value)实时获取cube_num和vector_num ``` 以上代码展示控核接口的调用,对应acl接口调用,由于版本问题,需要使用dopen调用,防止由于版本问题编译不通过。同时需要runtime记录每次算子调用使用的Stream,如果出现Stream切换,需要重新调用aclError aclrtUseStreamResInCurrentThread(aclrtStream stream)接口将Stream绑定到当前线程。 线程级控核接口set_stream_limit可以在执行期间多次调用,将分核策略绑定到对应的stream上,后续在对应Stream运行的算子将采纳最近一次绑定的分核策略。 ##### 需求拆解 后端(#ID1FLX):后端提供分核控制接口,可以供用户调用(共5个接口);runtime运行时管理,能够调用CANN对应接口实现device级别和stream级别控核。预期时间:1030 算子cache(https://gitee.com/mindspore/mindspore/issues/ICXUJ3):aclnn算子调用支持分核后,框架侧需要对算子调用的tiling进行缓存变更,由以往根据shape+type+op_type生成的hashkey,变更为由shape+type+op_type+cube_num+vector_num生成hashkey。预期时间:1030 DVM:可以通过接入CANN接口对aclnn分核同样的调用形式,来实现DVM算子控核。预期时间:1030 ### 2 收益场景 #### 2.1 MoE多副本-多核并行,实现大范围并发、高密流水&掩盖 AS IS: 现状:1)Cube利用率不足 & Vector占比高;2)EP All2All通信开销大且引入断流开销,专家负载不均时开销进一步加剧  TO BE: 多核并行- 基于多副本并行(token维切片),每个副本切片独立计算流,多核并发实现高密流水,同时达成大范围并发&掩盖: 1)切片后单个切片计算量降低,通过对分片的计算&通信做分核并发和执行序编排(Cube-Cube并发、Cube-Vector并发、通算并发)冲高算力利用率,支持细粒度切片、提升流水掩盖率; 2)单边通信替换集合通信,消除非必要同步,单副本切片load完自己所需数据即可启动后续计算、无需等待其他卡,消除断流开销; 3)单边通信算子需要占用少量Vector核资源(实测DeepSeek模型典型场景单边通信4~8核为最优分核策略),用户可结合单边通信的分核接口进一步提升通算并发效率,提升流水密度  #### 2.2 核级负载均衡  针对MOE训练专家负载不均挑战: - AS IS: 不同卡专家计算与通信不均衡,端到端性能下降 - TO BE: 热点计算任务做切片,分配到非热点节点,多核并行掩盖Load/Store开销,端到端性能提升30%~50% ## 测试设计和测试计划. | MindSpore对用户暴露接口 | 类型 | 功能 | 支持模式 | 功能详解 | |--------------------------------------------------------------------|-------|-------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------| | with ms.runtime.MyMsJitStreamCtx(s1) | 分流 | 图模式下支持多流 | 图模式,支持入图 | | | Event.record() | 执行序控制 | 发送信号,等待wait | 图模式,支持入图 | | | Event.wait() | 执行序控制 | 等待record信号 | 图模式,支持入图 | | | ms.set_device_limit(device, cube_num=-1, vector_num=-1) | 分核 | 进程级控核设置接口 | 动态图模式 | 开启device粒度资源分配,为device设置各加速器的数量。 | | ms.get_device_limit(device) | 分核 | 进程级控核查询接口 | 动态图模式 | 获取device正在使用的资源分配。 | | ms.set_stream_limit(stream, cube_num=-1, vector_num=-1) | 分核 | 线程级控核设置接口 | 动态图模式 | 开启stream粒度资源分配,为stream设置各加速器的数量。如果没有setLimit,则使用platform里原有的芯片规格 | | ms.reset_stream_limit(stream) | 分核 | 线程级控核重置接口 | 动态图模式 | 关闭stream粒度资源分配功能。调用aclrtSetStreamResLimit接口设置指定Stream的Device资源限制后,可调用本接口重置指定Stream的Device资源限制,恢复默认配置,此时可通过aclrtGetStreamResLimit接口查询默认的资源限制。 | | ms.get_stream_limit(stream) | 分核 | 线程级控核查询接口 | 动态图模式 | 查询stream对应的资源分配信息 | | with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1) | 分核 | 线程级控核设置接口 | 图模式,支持入图 | 开启stream粒度资源分配,为stream设置各加速器的数量。如果没有setLimit,则使用platform里原有的芯片规格 | 结合多流、执行序、分核,主要通过构造以下场景进行测试验证,不开启DVM自动融合,支持aclnn算子分核。 多流: 1、双流单算子:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,其中Matmul算子运行在主S1,Add算子运行在S2,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期Matmul算子和Add算子可以并发执行,即存在执行时间重叠。 2、双流多算子:构建网络结构,使用多个Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,其中主流运行多个Matmul/Add算子,其余流也运行多个Matmul/Add算子,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期两个流的算子可以并发执行,即存在执行时间重叠。 3、多流多算子:构建网络结构,使用多个Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,其中Matmul算子运行在主流,MatMul/Add算子运行在其余流,并通过with ms.runtime.MyMsJitStreamCtx控制算子执行流,预期多流的算子可以并发执行,即存在执行时间重叠。注意,由于hostbound,可以在每个流最开始执行一个超大shape算子用例,减小hostbound,让其正常并发。 执行序: 1、单event单record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2,若直接执行,预期Matmul和Add存在时间并发,在S1执行Matmul后插入Event.record(),在S2的Add算子执行前插入Event.wait(),可以让Matmul和Add不存在并发,即控制两者的执行时间,不存在时间重叠。 2、多event多record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,若直接执行,预期每个流的算子均存在时间并发重叠,若创建5个event,重复在每个流执行前插入Event.wait(),并在每个流的最后插入Event.record(),控制每个流的算子执行时机,可以让算子执行不存在时间重叠。 3、单event对应多record:构建网络结构,使用Matmul算子和Add算子多流并发,主流为S1,使用ms.runtime.Stream()创建S2、S3、S4、S5,可以在主流执行Event.record(),在其余分流的开始执行同一个Event对象的Event.wait(),预期可以控制S2、S3、S4、S5的算子并发,并且均在S1之后执行。 分核: 1、动态图测试device控核:在单流时,使用ms.runtime.set_device_limit(device, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_device_limit(device)的返回值能够对应,单流算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 2、动态图测试Stream控核-单次调用:在单流时,使用ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_stream_limit(device)的返回值能够对应,单流算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 3、动态图测试Stream控核-多次调用:在单流时,使用ms.runtime.set_stream_limit(stream, cube_num=-1, vector_num=-1)控制核数,使用多个算子,例如matmul,在每个算子调用之间插入set_stream_limit,且配置不同核数,预期算子的核数使用和最近一次配置一致;在使用reset_stream_limit后,后面算子的运行使用核数和不配置Stream分核时一致。 4、静态图测试Stream控核-单次调用:在单流时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制核数,且和ms.runtime.get_stream_limit(device)的返回值能够对应,with作用域内算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致。 5、静态图测试Stream控核-多次调用:在单流时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制核数,使用多个算子,例如matmul,在每个算子调用之间插入StreamLimitCtx,且配置不同核数,with作用域内算子运行的核数(从kernel_details.csv的block_dim)和配置核数一致,作用域外使用默认核数。 多流、执行序、多核交叉验证: 1、动态图测试多核并行-功能验证:使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发,并通过Event.record和Event.wait控制算子的执行序,例如让流1的Matmul和流2的Add算子并发,同时,使用ms.runtime.set_stream_limit(device, cube_num=-1, vector_num=-1)控制MatMul算子和Add算子的核数,例如让Matmul的cube_num为24,同时让Add算子的vector_num为20,预期可以正常并发执行,且流1的Matmul和流2的Add的执行核数和预期一致。 2、静态图测试多核并行-功能验证:使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发,并通过Event.record和Event.wait控制算子的执行序,例如让流1的Matmul和流2的Add算子并发,同时,使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制MatMul算子和Add算子的核数,例如让Matmul的cube_num为24,同时让Add算子的vector_num为20,预期可以正常并发执行,且流1的Matmul和流2的Add的执行核数和预期一致。 3、算子PASS优化验证:构造一个继承PatternProcessPass基类的pass(MatmulAssignaddFusion)结构,融合前节点都不带stream_id或core_num属性,预期可以融合且融合后节点不带stream_id或core_num属性;使用分流将算子分散在不同流,预期不会融合;使用分核接口将算子的核数设置为不同值,预期不会融合。 4、算子Cache优化验证:构造多核并行代码,使用ms.runtime.Stream()和ms.runtime.Event()创建多个流和事件,多个流有N个算子执行,可以让多个流的算子并发。在流内使用with ms.runtime.StreamLimitCtx(stream, cube_num=-1, vector_num=-1)控制算子执行核数,且对同一算子多次执行(不改变输入shape和算子),而且每次配置的核数一致,可以开启INFO日志观察,预期算子执行时Cache的hash_id一致。 ## 期望的反馈时间. ## CC List. 前端: @ginfung 、 @Margaret_wangrui 、@Qiao_Fu 后端: @zpac 、 @zhangyinxia DVM:@gaoxiong1 算子调用Cache: @hbhu_bin 后端融合pass相关优化:@yuchaojie ## 其他补充信息. ## Before submitting a new issue... - [x] Make sure you already searched for previous [RFCs](https://gitee.com/mindspore/mindspore/issues?q=is%3Aall+label%3ARFC+sort%3Arecently-updated).
评论 (
14
)
登录
后才可以发表评论
状态
DONE
VALIDATION
CLOSED
TODO
ACCEPTED
WIP
DONE
REJECTED
负责人
未设置
guangpengz
guangpengz
负责人
协作者
+负责人
+协作者
标签
RFC
parallel
akg
compiler-frontend
compiler-backend
runtime
gitee
test
demo
未设置
项目
未立项任务
未立项任务
里程碑
MindSpore 2.8.0
未关联里程碑
Pull Requests
未关联
未关联
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
未关联
分支 (
-
)
标签 (
-
)
开始日期   -   截止日期
-
置顶选项
不置顶
置顶等级:高
置顶等级:中
置顶等级:低
优先级
不指定
严重
主要
次要
不重要
预计工期
(小时)
参与者(8)
Python
1
https://gitee.com/mindspore/mindspore.git
git@gitee.com:mindspore/mindspore.git
mindspore
mindspore
mindspore
点此查找更多帮助
搜索帮助
Git 命令在线学习
如何在 Gitee 导入 GitHub 仓库
Git 仓库基础操作
企业版和社区版功能对比
SSH 公钥设置
如何处理代码冲突
仓库体积过大,如何减小?
如何找回被删除的仓库数据
Gitee 产品配额说明
GitHub仓库快速导入Gitee及同步更新
什么是 Release(发行版)
将 PHP 项目自动发布到 packagist.org
评论
仓库举报
回到顶部
登录提示
该操作需登录 Gitee 帐号,请先登录后再操作。
立即登录
没有帐号,去注册