[技术干货-算子使用] Mindspore 控制流中存在原地更新操作类副作用算子时循环值不更新问题记录
关于mindspore 原地更新类算子的一点思考记录如下:
现象记录:
原始测试代码

错误结果复现:

分析:
如果在场景中加入42行的copy()操作此时cpu的结果就会正确,但是gpu的结果则不受copy做操作的影响
修改后测试结果:

Mindspore 控制流场景中,我们的H是由mnp.one 新建出来的,但是其底层是调用的numpy的封装申请出来的是一个const的数据,这样的数据通过赋值给H,如果H在传递到其他地方,其内部被修改,下次在赋值,这块const的地址不会新创建,那么下次循环H的
值就会不对了。
解决办法:
- 打開42行copy的注釋
- 將k 以及 k_iter的值從tensor改成数值0,这样while控制流会将这些body 展开,相当于 H的值存储了多份也不会有任何更改
- 查看tensorscatterNdUpdate 后端实现,确定其实现是否是直接修改输入并且返回输入的操作
结果发现:其实现是在input的基础上inplace操作然后拷贝到输出地址,这样修改了原先的干净的输入地址,倘若存在内存复用其生命周期还未结束,那么其他地方拿到的值就会被污染,因此修改实现为拷贝输入到输出然后在做inplace 操作,修改后代码,这样不论输入的生命周期是否结束,均不会影响到原来的值

总结:
1.为什么静态图下会出错?
动态图中不会有静态的推断,H的值每次都会新赋值不同地址,因此上次的H的地址内容被修改,不会有影响
- 为什么cpu会出错 gpu 不出错?
因为cpu不存在host和device的概念,在图运行时cpu inplace类算子做相关操作时直接污染了cpu的输入原始地址,但是gpu操作时会先将host侧内容拷贝到device侧操作那么device侧输入原始地址被污染没关系,下次循环子图时会有新的地址过来,无影响。
- 解决办法加copy操作好还是直接修改后端算子好?
3.1. 直接加copy会导致某一后端正确(cpu)但某一后端无影响是冗余操作,不妥且只是规避并没有解决这个问题。
3.2. 直接修改后端算子的话除了能解决当前场景的问题,也能避免内存复用引用计数时因为输入的生命周期过长,而输入的原始地址被污染产生更难定位的问题。
3.3. 同时也能知道mindspore的机制在后端是不支持直接的inplace操作的,一切对输入的inplace操作,都存在一定的隐患,因此编写算子过程中不光cpu 其他gpu ascend,均应该先将输入拷贝到输出,再在输出中做inplace 操作,不管要保证输出地址的合法性也要保证输入地址没有被污染。因此编写原地更新操作类算子应该遵循上述准则才可以。
对应pr 修改:
https://gitee.com/mindspore/mindspore/pulls/27203/files
https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=171550&fromuid=642331
[技术干货-算子使用] Mindspore 控制流中存在原地更新操作类副作用算子时循环值不更新问题记录的更多相关文章
- JAVA中的集合容器操作类
目录 JAVA中的集合容器操作类 List集合 ArrayList的操作方法说明 LinkedList Stack Set Map Queue 总结 JAVA中的集合容器操作类 Java容器类库总共分 ...
- mybatis高级(2)_数据库中的列和实体类不匹配时的两种解决方法_模糊查询_智能标签
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE mapper PUBLIC "- ...
- 技术干货丨如何在VIPKID中构建MQ服务
小结: 1. https://mp.weixin.qq.com/s/FQ-DKvQZSP061kqG_qeRjA 文 |李伟 VIPKID数据中间件架构师 交流微信 | datapipeline201 ...
- golang中使用mongodb的操作类以及如何封装
mgo简介 mongodb官方没有关于go的mongodb的驱动,因此只能使用第三方驱动,mgo就是使用最多的一种. mgo(音mango)是MongoDB的Go语言驱动,它用基于Go语法的简单API ...
- 利用FastJson,拼接复杂嵌套json数据&&直接从json字符串中(不依赖实体类)解析出键值对
1.拼接复杂嵌套json FastJson工具包中有两主要的类: JSONObject和JSONArray ,前者表示json对象,后者表示json数组.他们两者都能添加Object类型的对象,但是J ...
- java并发编程基础 --- 7章节 java中的13个原子操作类
当程序更新一个变量时,如果多线程同时更新这个变量,可能得到期望之外的值,比如变量 i=1,A线程更新 i+1,B线程也更新 I+1,经过两个线程的操作之后可能 I不等于3,而是等于2.因为A和B线程更 ...
- Java中的13个原子操作类
java.util.concurrent.atomic包一共提供了13个类.属于4种类型的原子更新方式,分别是原子更新基本类型,原子更新数组,原子更新引用和原子更新属性.Atomic包里的类基本都是使 ...
- 关于for与forEach遍历集合中对集合进行操作的问题
遍历List集合,在循环中再对List集合进行操作,有时候会遇到ConcurrentModificationException(并发修改异常);其实只有在forEach循环集合再对集合操作会发生异常: ...
- 技术干货 | 基于MindSpore更好的理解Focal Loss
[本期推荐专题]物联网从业人员必读:华为云专家为你详细解读LiteOS各模块开发及其实现原理. 摘要:Focal Loss的两个性质算是核心,其实就是用一个合适的函数去度量难分类和易分类样本对总的损失 ...
随机推荐
- 游戏案例|Service Mesh 在欢乐游戏的应用演变和实践
作者 陈智伟,腾讯 12 级后台专家工程师,现负责欢乐游戏工作室公共后台技术研发以及团队管理工作.在微服务分布式架构以及游戏后台运维研发有丰富的经验. 前言 欢乐游戏工作室后台是分布式微服务架构,目前 ...
- k8s StatefulSet控制器-独立存储
k8s-StatefulSet控制器-独立存储 1. StatefulSet控制器-独立存储 独享存储:StatefulSet的存储卷使用VolumeClaimTemplate创建,称为卷申请模板,当 ...
- Linux系统时钟与硬件时钟
linux系统有两个时钟:一个是由主板电池驱动的硬件时钟(Real Time Clock),也叫做RTC或者叫CMOS时钟.当操作系统关机的时候,用这个来记录时间,但是对于运行的系统是不用这个时间的: ...
- shell获取目录下(包括子目录)所有文件名、路径、文件大小
一例shell脚本:取得目录下(包括子目录)所有文件名.路径与文件大小. 代码,shell脚本: lsdir.sh #!/bin/bash # #site: www.jquerycn.cn funct ...
- 统计网卡流量的两段shell脚本(使用ifconfig)
一个很小巧的shell脚本,使用ifconfig的不间断输出来统计网卡的流量,有需要的朋友可以参考下 使用shell脚本计算Linux网卡流量,方法中最关键点: ifconfig $eth_name ...
- 观察者模式之spring事件机制
ddsspring中的事件机制使用到设计模式中的观察者模式 ,观察者模式有两个概念,1.观察者.被观察者.2.被观察者做出相应得动作,观察者能接收到.不分析设计模式,学习下spring中的事件机制实际 ...
- java的bio和nio写入及读取txt文件
一.bio的写入及读取 1.采用bio之BufferedWriter 写入文件 public static void main(String[] args) throws IOException { ...
- Abp Vnext 替换Redis的实现为csredis
Host项目安装csredis的nuget包和data protect包并 移除 Microsoft.Extensions.Caching.StackExchangeRedis Microsoft.A ...
- 象群游牧算法--EHO
象群游牧算法的数学模型 象群的游牧行为非常复杂,但是其中一些行为可以帮助我们寻找全局最优解和局部最优解.对此,进行数学建模为: (1) 象群的每个部落都有固定数目的大象: (2) 每次迭代中,部落中都 ...
- who 命令的实现
who 命令显示 当前已经登录的用户 查看连接帮助: man who who(1) 表示who的小结编号. NAME 包含命令的名字以及对这个命令的简短说明 SYNOPSYS 给出命令的用法说明,命 ...