1.Vue2.0源码阅读(2) —vue.nextTicket()
2.Vue3源码系列 (一) watch
3.经典网络结构搜索算法 SPOS,源码快速完成模型压缩
Vue2.0源码阅读(2) —vue.nextTicket()
揭开Vue.nextTick之谜
在vue圈子中,源码有一句广为流传的源码“都市传说”:“遇事不决,问nextTick。源码”这句话背后的源码nextTick究竟是何物?根据官方文档的解释,nextTick()是源码报表开发平台源码在下次DOM更新循环结束之后执行延迟回调。其核心功能是源码在数据更新后自动调用回调函数,获取更新后的源码DOM。接下来,源码我们将深入源码,源码一探nextTick的源码真谛。
将nextTick定义至Vue原型链的源码代码位于src/core/instance/render.js,具体实现则在src/core/util/next-tick.js。源码nextTick接受两个参数:函数cd(实际使用场景中,源码为延迟执行的源码函数)与this上下文。内部定义了一个回调函数数组callbacks,当cb存在时将其添加至数组,同时将回调函数的上下文指向组件的this;若cb不存在,则将resolve函数添加至数组。接着判断pending值,其用于控制状态。当pending值为false,表示无回调函数正在执行,进而执行timerFunc函数。timerFunc函数在cb不存在且浏览器支持Promise时返回一个Promise,允许在不传入回调的情况下通过this.$nextTick().then(cb)进行调用。
timerFunc看似实现关键,c regex 源码实则执行逻辑围绕Promise、MutationObserver、setImmediate与setTimeout(f(), 0)等方法展开。若系统支持Promise,则使用Promise执行延时;不支持Promise时,依次判断是否支持MutationObserver、setImmediate或setTimeout,选择合适的方法执行flushCallbacks函数。
flushCallbacks函数负责将pending状态设为false,并将callbacks数组复制至copies数组,清空callbacks。接着遍历copies数组,依次执行回调函数(即传入nextTick的cb函数)。至此,我们理解了nextTick的核心机制与使用场景。
MutationObserver:在源码阅读中,我们发现若系统不支持Promise,则使用MutationObserver作为替代方案。MutationObserver是监听DOM树变更的接口,其设计用于替代DOM3 Events规范中的Mutation Events功能。简单理解,MutationObserver用于监听DOM变动,当DOM发生任何更改时,它会接收到通知。
MutationObserver的使用方式如代码所示,实例化MutationObserver并指定回调函数与需要监控的源码管理 保密DOM元素与变动类型。调用observer.observe(dom, options)方法进行观察。options对象中定义了需要观察的变动类型,如childList、attributes、characterData等。
下面通过一个简单的demo来理解MutationObserver。在运行该demo后,屏幕显示了,说明文本节点已添加至DOM中。然而,控制台打印的I值只有1,这意味着DOM变动只触发了一次。这表明MutationObserver在异步处理DOM变化,直到页面上所有DOM操作完成时执行一次,实现高效处理。
在nextTick中,MutationObserver用于触发flushCallbacks函数。通过文本节点的操作触发MutationObserver,从而执行flushCallbacks。至此,我们理解了nextTick的实现与MutationObserver的用法。
源码阅读让我们发现,nextTick并非传说中的神物,其主要应用场合与DOM操作相关。在遇到无法在DOM更新前操作DOM的情况时,可以考虑使用nextTick。iwebshop源码包由于nextTick在DOM更新循环结束后执行,因此在created钩子中操作DOM成为可能,实现目标。
Vue3源码系列 (一) watch
本文深入解析 Vue3 中 watch 的机制。首先,我们了解 watch 接收三个参数:监听的数据源 source、回调 cb 以及可选的 options。options 包括 immediate、deep、flush、onTrack 和 onTrigger,用于控制立即执行、深度监听、回调时机以及收集依赖和触发更新时的自定义函数。回调 cb 接收 value、oldValue 和 onCleanUp 参数,用于执行特定操作,如响应表格页码变化重新请求数据,并在副作用清理时调用 onCleanUp 函数。
watch 支持监听单个数据或多个数据,其参数类型包括 WatchSource、响应式对象、MultiWatchSources 和 Readonly。单个数据源可以是 WatchSource 或响应式的对象,多个数据源则为 MultiWatchSources 或 Readonly。
watch 的nginx epoll 源码核心在于 doWatch 函数,它接收与 watch 类似的参数。在源码中,doWatch 负责实现 watch 的逻辑。首先,它会检查是否提供了回调函数 cb。如果没有,且 options 中设置了 immediate 和 deep,会抛出警告,因为这些选项只对有回调的 doWatch 签名有效。接着,设置 getter,并配置强制触发和深度监听。根据 source 的类型,doWatch 进行不同的处理。
在处理源数据后,doWatch 会创建 effect,这是 Vue3 中实现响应式的关键。effect 通过 getter 获取当前值,然后在回调函数中使用 newValue 和 oldValue。这使得 watch 能在数据变化时触发回调函数,执行相应的操作。
总结,本文详细阐述了 Vue3 中 watch 的工作原理,从参数类型、回调函数到核心实现 doWatch 函数,全面深入地解析了 watch 的机制,帮助开发者更好地理解和运用 Vue3 的响应式特性。通过本文,读者可以深入了解 Vue3 watch 的内部工作流程,为构建高效、响应式的 Vue 应用提供技术支持。
经典网络结构搜索算法 SPOS,快速完成模型压缩
Single Path One Shot(SPOS)算法是一种高效、低成本的神经网络结构搜索方法,相较于传统的基于强化学习、进化算法等方法,SPOS算法显著降低了搜索成本。MMRazor是一个深度学习模型压缩算法库,支持包括网络结构搜索、剪枝、蒸馏在内的主流技术方向,为OpenMMLab其他算法库提供即插即用、可自由组合的模型压缩算法,使得模型轻量化更为简便快捷。本文将对SPOS算法原理、搜索空间、MMRazor以及在MMRazor中的实现进行详细的解读,内容干货满满。1. SPOS算法介绍
1.1 原理介绍 SPOS算法在ECCV年提出,针对传统NAS算法中网络权重耦合度过高的问题,SPOS提出将网络权重的训练与网络结构的搜索进行解耦。首先训练超网络的权重,然后从超网络中搜索最优的子网络架构,最后对最优子网进行从头开始的训练。整个运行过程分为三个步骤:超网权重训练:使用单路径候选网络构成的超网络,通过优化每层的选择会构建一条单路径子网络。通过优化整个超网的权重完成整个优化过程。
网络结构搜索:从训练好的超网中通过进化算法找到最优的子网络。
重训练子网:在找到最优子网络后,从头开始训练。
1.2 搜索空间介绍 SPOS论文中提到的搜索空间丰富,包括choiceblock搜索、通道搜索和混合精度量化搜索。当前官方源码中仅提供了choiceblock搜索部分。SPOS的搜索空间结构如下表所示,CB代表choiceblock,共包含个CB。CB内部操作主要受ShuffleNetv2启发,提供了四种操作。2. MMRazor简介
MMRazor是一个深度学习模型压缩算法库,支持网络结构搜索、剪枝、蒸馏等主流技术方向,为OpenMMLab其他算法库提供即插即用、可自由组合的模型压缩算法,实现模型轻量化更为简便快捷。MMRazor的整体设计思想与OpenMMLab保持一致,支持多种算法库。其组织架构分为组件层、算法层和应用层。3. MMRazor中超网的构建方式
神经网络结构搜索算法中,超网的实现至关重要。算法框架至少需要具备以下功能:搜索对象是可变化的,如SPOS中的不同候选操作;搜索算法能够指定选择某个候选操作的功能。MMRazor通过引入Mutable和Mutator对象实现上述功能:通过PlaceHolder提供占位符功能,用户定义的可变位置,在调用Mutator中的convert方法后转化为Mutable对象。通过这种方式使超网变成可搜索对象Mutable,后续与Mutator进一步完成NAS任务。4. SPOS在MMRazor中的实现
4.1 环境安装
安装教程请参考:[MMRazor文档链接]。以cuda.1、pytorch1.9为例,首先安装cuda、torch、mmcv包,其中mmcv-full表示采用预编译包的安装方式,还需注意对应cuda以及torch的版本。mmcv安装详细方式以及cuda、torch、mmcv版本对应关系可见:[mmcv文档链接]。以torch1.9为例进行环境安装。 安装MMRazor推荐使用MIM安装或直接使用pip安装:pip install MMRazor。也可以通过源码安装。4.2 Config介绍
由于训练SPOS分为三个阶段,对应三个config: 以spos_supernet_shufflenetv2_8xb_in1k.py为例,config中主要有model、algorithm、mutator三个对象,其中algorithm中包含architecture对象,architecture对象中则包含model。在初始化algorithm的过程中,algorithm会初始化architecture,并根据是否传入mutator、pruner、distiller来决定是否初始化这三个对象。4.3 超网权重训练(Pre-training)
完成以上准备工作后,进行第一个阶段训练:超网权重训练。这个过程需要不断地从超网中采样子网,迭代优化子网参数,最终得到优化后的超网。训练命令如下所示,SPOS中超网训练通过随机采样的方式优化网络,每次前向训练一个batch的过程中会随机采样一个子网络。4.4 网络结构搜索(Evolution search)
此过程初始化候选池,从预训练好的SuperNet中得到Subnet在测试集上的结果,根据得分更新候选池的Topk并执行Mutation和CrossOver操作,得到最优子网的网络结构。训练命令如下所示,这里需要用到上一步超网权重的路径$STEP1_CKPT。具体Searcher选择的是EvolutionSearcher。4.5 重训练子网(Retrain)
在上一步通过进化算法得到最优子网结构后,将其对应的子网络从头进行训练,得到最终的可用网络模型。训练命令如下所示,需要将algorithm.mutable_cfg参数传入,该参数为上一步得到的yaml文件位置。训练过程与训练普通分类网络完全一致。5. 总结
本文详细解读了经典的网络结构搜索算法SPOS及其在MMRazor中的实现流程。SPOS算法能够与各类代码库搭配使用,如与MMDetection库的配合,实现便捷的DetNAS算法。MMRazor不仅包含NAS相关算法,还有蒸馏和剪枝等功能。欢迎体验,如对您有帮助,欢迎点个star。更多内容可查看[相关链接]。