[{"data":1,"prerenderedAt":421},["ShallowReactive",2],{"content-query-2WfNWDhiYP":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"body":13,"_type":415,"_id":416,"_source":417,"_file":418,"_stem":419,"_extension":420},"/news/en/2760","en",false,"","Project Introduction | Experience in Developing MindSpore Insight, an AI-powered Visualization Tool","MindSpore Insight is a visualized debugging and tuning tool. In this blog, I will briefly introduce MindSpore Insight and the reactivity principle of the development framework Vue used in development.","2022-12-20","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/09/14/24a1ff3c7a494d9ba4ba454d8b465ab9.png","news",{"type":14,"children":15,"toc":412},"root",[16,24,34,49,54,68,83,91,105,117,124,129,134,139,144,152,215,220,225,234,244,254,259,264,269,274,279,284,289,294,299,304,309,314,319,324,329,334,339,344,354,362],{"type":17,"tag":18,"props":19,"children":21},"element","h1",{"id":20},"project-introduction-experience-in-developing-mindspore-insight-an-ai-powered-visualization-tool",[22],{"type":23,"value":8},"text",{"type":17,"tag":25,"props":26,"children":27},"p",{},[28],{"type":17,"tag":29,"props":30,"children":31},"strong",{},[32],{"type":23,"value":33},"Author: Zhang Yutao | School: Zhengzhou University",{"type":17,"tag":25,"props":35,"children":36},{},[37,42,44],{"type":17,"tag":29,"props":38,"children":39},{},[40],{"type":23,"value":41},"01",{"type":23,"value":43}," ",{"type":17,"tag":29,"props":45,"children":46},{},[47],{"type":23,"value":48},"Overview",{"type":17,"tag":25,"props":50,"children":51},{},[52],{"type":23,"value":53},"MindSpore Insight is a visualized debugging and tuning tool. As a developer, I have contributed to the development of certain features of MindSpore Insight. In this blog, I will briefly introduce MindSpore Insight and the reactivity principle of the development framework Vue used in development.",{"type":17,"tag":25,"props":55,"children":56},{},[57,62,63],{"type":17,"tag":29,"props":58,"children":59},{},[60],{"type":23,"value":61},"02",{"type":23,"value":43},{"type":17,"tag":29,"props":64,"children":65},{},[66],{"type":23,"value":67},"Introduction to MindSpore Insight",{"type":17,"tag":25,"props":69,"children":70},{},[71,73,81],{"type":23,"value":72},"MindSpore Insight provides easy-to-use tuning and debugging capabilities for MindSpore. It records data including scalars, tensors, graphs, computational graphs, model hyperparameters, and training elapsed time in files during training, and analyzes and displays the data on visualized pages. The following figure shows the macro architecture of MindSpore Insight. Summary logs are model logs generated during model training in MindSpore. They are decoded by Python and the corresponding data is processed into APIs in JSON format. In this case, the frontend can request the APIs to display corresponding functions. For details, visit the official website at ",{"type":17,"tag":74,"props":75,"children":79},"a",{"href":76,"rel":77},"https://www.mindspore.cn/mindinsight/docs/en/master/index.html",[78],"nofollow",[80],{"type":23,"value":76},{"type":23,"value":82},".",{"type":17,"tag":25,"props":84,"children":85},{},[86],{"type":17,"tag":87,"props":88,"children":90},"img",{"alt":7,"src":89},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/09/14/46e77bb339f54ca18f77a2f0a29fa313.png",[],{"type":17,"tag":25,"props":92,"children":93},{},[94,99,100],{"type":17,"tag":29,"props":95,"children":96},{},[97],{"type":23,"value":98},"03",{"type":23,"value":43},{"type":17,"tag":29,"props":101,"children":102},{},[103],{"type":23,"value":104},"Discussion on the Reactivity Principle of Vue 2",{"type":17,"tag":25,"props":106,"children":107},{},[108,110,115],{"type":23,"value":109},"Vue is a JavaScript framework for building user interfaces (UIs) on the web. It is built based on standard HTML, CSS, and JavaScript, and provides a declarative, component-based programming model to help you efficiently develop UIs. Its core features include declarative rendering and reactivity. Vue can automatically track JavaScript state changes and efficiently update the DOM when changes happen. As shown in the figure below, when information in the ",{"type":17,"tag":29,"props":111,"children":112},{},[113],{"type":23,"value":114},"data",{"type":23,"value":116}," property changes, the corresponding view is automatically updated without the need for manually operating the DOM. So how does Vue know the data to be updated? This involves the implementation of reactivity principle of Vue.",{"type":17,"tag":25,"props":118,"children":119},{},[120],{"type":17,"tag":87,"props":121,"children":123},{"alt":7,"src":122},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/09/14/48f83736f34547a98ed07e5d96054f85.png",[],{"type":17,"tag":25,"props":125,"children":126},{},[127],{"type":23,"value":128},"The Vue reactivity refers to that the view is driven by data. That is, when data changes, the view is re-rendered. The following three points need to be considered during the implementation of this process:",{"type":17,"tag":25,"props":130,"children":131},{},[132],{"type":23,"value":133},"● Data hijacking: Track data changes.",{"type":17,"tag":25,"props":135,"children":136},{},[137],{"type":23,"value":138},"● Dependency collection: Collect data on which a view depends.",{"type":17,"tag":25,"props":140,"children":141},{},[142],{"type":23,"value":143},"● Notification view: When data changes, the notification view is partially updated.",{"type":17,"tag":25,"props":145,"children":146},{},[147],{"type":17,"tag":29,"props":148,"children":149},{},[150],{"type":23,"value":151},"3.1 Data Hijacking and Dependency Collection",{"type":17,"tag":25,"props":153,"children":154},{},[155,160,162,167,169,174,176,181,183,188,190,194,196,201,203,207,209,213],{"type":17,"tag":29,"props":156,"children":157},{},[158],{"type":23,"value":159},"Data hijacking",{"type":23,"value":161}," refers to intercepting the behavior of accessing or modifying a certain property of an object through a piece of code, and performing additional operations or modifying the returned result. The following code explains data hijacking well. Assigning a value to the ",{"type":17,"tag":29,"props":163,"children":164},{},[165],{"type":23,"value":166},"name",{"type":23,"value":168}," property of an object (",{"type":17,"tag":29,"props":170,"children":171},{},[172],{"type":23,"value":173},"obj",{"type":23,"value":175},") triggers the ",{"type":17,"tag":29,"props":177,"children":178},{},[179],{"type":23,"value":180},"set",{"type":23,"value":182}," function in the ",{"type":17,"tag":29,"props":184,"children":185},{},[186],{"type":23,"value":187},"defineProperty",{"type":23,"value":189}," method, and accessing the value of the ",{"type":17,"tag":29,"props":191,"children":192},{},[193],{"type":23,"value":166},{"type":23,"value":195}," property of the object triggers the ",{"type":17,"tag":29,"props":197,"children":198},{},[199],{"type":23,"value":200},"get",{"type":23,"value":202}," function. Here, the ",{"type":17,"tag":29,"props":204,"children":205},{},[206],{"type":23,"value":180},{"type":23,"value":208}," and ",{"type":17,"tag":29,"props":210,"children":211},{},[212],{"type":23,"value":200},{"type":23,"value":214}," functions intercept the behavior of accessing and modifying the object property, and additional operations can be written to them. This is called data hijacking.",{"type":17,"tag":25,"props":216,"children":217},{},[218],{"type":23,"value":219},"/*",{"type":17,"tag":25,"props":221,"children":222},{},[223],{"type":23,"value":224},"Object.defineProperty(obj,prop,descriptor)",{"type":17,"tag":25,"props":226,"children":227},{},[228,232],{"type":17,"tag":29,"props":229,"children":230},{},[231],{"type":23,"value":173},{"type":23,"value":233},": object whose property is to be defined",{"type":17,"tag":25,"props":235,"children":236},{},[237,242],{"type":17,"tag":29,"props":238,"children":239},{},[240],{"type":23,"value":241},"prop",{"type":23,"value":243},": name of the property to be defined or modified",{"type":17,"tag":25,"props":245,"children":246},{},[247,252],{"type":17,"tag":29,"props":248,"children":249},{},[250],{"type":23,"value":251},"descriptor",{"type":23,"value":253},": descriptor of the property to be defined or modified",{"type":17,"tag":25,"props":255,"children":256},{},[257],{"type":23,"value":258},"Output:",{"type":17,"tag":25,"props":260,"children":261},{},[262],{"type":23,"value":263},"Data hijacking set name: Jack",{"type":17,"tag":25,"props":265,"children":266},{},[267],{"type":23,"value":268},"Data hijacking get name: Jack",{"type":17,"tag":25,"props":270,"children":271},{},[272],{"type":23,"value":273},"Jack",{"type":17,"tag":25,"props":275,"children":276},{},[277],{"type":23,"value":278},"*/",{"type":17,"tag":25,"props":280,"children":281},{},[282],{"type":23,"value":283},"const obj={}",{"type":17,"tag":25,"props":285,"children":286},{},[287],{"type":23,"value":288},"Object.defineProperty(obj,\"name\",{",{"type":17,"tag":25,"props":290,"children":291},{},[292],{"type":23,"value":293},"get(){",{"type":17,"tag":25,"props":295,"children":296},{},[297],{"type":23,"value":298},"console.log(\"Data hijacking get name :\",nameVal);",{"type":17,"tag":25,"props":300,"children":301},{},[302],{"type":23,"value":303},"return nameVal;",{"type":17,"tag":25,"props":305,"children":306},{},[307],{"type":23,"value":308},"},",{"type":17,"tag":25,"props":310,"children":311},{},[312],{"type":23,"value":313},"set(newVal){",{"type":17,"tag":25,"props":315,"children":316},{},[317],{"type":23,"value":318},"console.log(\"Data hijacking set name :\",newVal)",{"type":17,"tag":25,"props":320,"children":321},{},[322],{"type":23,"value":323},"nameVal = newVal",{"type":17,"tag":25,"props":325,"children":326},{},[327],{"type":23,"value":328},"}",{"type":17,"tag":25,"props":330,"children":331},{},[332],{"type":23,"value":333},"});",{"type":17,"tag":25,"props":335,"children":336},{},[337],{"type":23,"value":338},"obj.name=\"Jack\";",{"type":17,"tag":25,"props":340,"children":341},{},[342],{"type":23,"value":343},"console.log(obj.name)",{"type":17,"tag":25,"props":345,"children":346},{},[347,352],{"type":17,"tag":29,"props":348,"children":349},{},[350],{"type":23,"value":351},"Dependency collection",{"type":23,"value":353},": When a view uses certain data, it depends on that data. Collecting the changing data is the process of dependency collection.",{"type":17,"tag":25,"props":355,"children":356},{},[357],{"type":17,"tag":29,"props":358,"children":359},{},[360],{"type":23,"value":361},"3.2 Implementation Principle",{"type":17,"tag":25,"props":363,"children":364},{},[365,369,371,378,380,386,388,394,396,402,404,410],{"type":17,"tag":87,"props":366,"children":368},{"alt":7,"src":367},"https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2023/09/14/53e1896a03894c0d9dbd037d24b2a114.png",[],{"type":23,"value":370}," The preceding figure (for details, visit ",{"type":17,"tag":74,"props":372,"children":375},{"href":373,"rel":374},"https://blog.csdn.net/Mikon%5C_0703/article/details/111367773",[78],[376],{"type":23,"value":377},"https://blog.csdn.net/Mikon\\_0703/article/details/111367773",{"type":23,"value":379},") is a flowchart of implementing the reactivity principle of Vue. It consists of three important parts: Observer: traverses data objects and uses Object.defineProperty() to add setter and getter to properties. In this case, if a value is assigned to an object, the setter is triggered and the data change can be observed. Event center (Dep): collects dependencies and notifies Watchers. If a property changes, the Watchers need to be notified to check whether updates are necessary. Because there are multiple Watchers, a message subscriber (publisher) Dep (management array of Watcher groups) is required to collect these Watchers and manage Observers and Watchers in a unified manner. Each Observer instance has a Dep instance. Watcher: initializes an instruction of the view to a Watcher, and replaces the template data or binds the corresponding function. In this case, when the Watcher receives the change of a property, it executes the corresponding update function to update the view. 3.3 Implementation in Vue Source Code Link to the source code of reactivity implementation of Vue 2: ",{"type":17,"tag":74,"props":381,"children":384},{"href":382,"rel":383},"https://github.com/vuejs/vue/blob/v2.6.14/src/core/observer",[78],[385],{"type":23,"value":382},{"type":23,"value":387}," Implementation of the Observer //",{"type":17,"tag":74,"props":389,"children":392},{"href":390,"rel":391},"https://github.com/vuejs/vue/blob/v2.6.14/src/core/observer/index.js",[78],[393],{"type":23,"value":390},{"type":23,"value":395}," walk (obj: Object) { const keys = Object.keys(obj) // Traverse data objects and use Object.defineProperty() to add setter and getter to all properties. for (let i = 0; i \u003C keys.length; i++) { defineReactive(obj, keys[i]) } } export function defineReactive ( obj: Object, key: string, val: any, customSetter?: ?Function, shallow?: boolean ) { const dep = new Dep() const property = Object.getOwnPropertyDescriptor(obj, key) if (property && property.configurable === false) { return } // cater for pre-defined getter/setters const getter = property && property.get const setter = property && property.set if ((!getter || setter) && arguments.length === 2) { val = obj[key] } let childOb = !shallow && observe(val) Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { const value = getter ? getter.call(obj) : val if (Dep.target) { dep.depend() // Collect dependencies. if (childOb) { childOb.dep.depend() if (Array.isArray(value)) { dependArray(value) } } } return value }, set: function reactiveSetter (newVal) { const value = getter ? getter.call(obj) : val /* eslint-disable no-self-compare */ if (newVal === value || (newVal !== newVal && value !== value){ return } /* eslint-enable no-self-compare */ if (process.env.NODE_ENV !== 'production' && customSetter) { customSetter() } // #7981: for accessor properties without setter if (getter && !setter) return if (setter) { setter.call(obj, newVal) } else { val = newVal } childOb = !shallow && observe(newVal) dep.notify() // When data changes, the event center Dep notifies the Watcher. } }) } Implementation of the Dep //",{"type":17,"tag":74,"props":397,"children":400},{"href":398,"rel":399},"https://github.com/vuejs/vue/blob/v2.6.14/src/core/observer/dep.js",[78],[401],{"type":23,"value":398},{"type":23,"value":403}," export default class Dep { static target: ?Watcher; id: number; subs: Array; constructor () { this.id = uid++ this.subs = [] } addSub (sub: Watcher) { this.subs.push(sub) } removeSub (sub: Watcher) { remove(this.subs, sub) } depend () { if (Dep.target) { Dep.target.addDep(this) } } notify () { // stabilize the subscriber list first const subs = this.subs.slice() if (process.env.NODE_ENV !== 'production' && !config.async) { // subs aren't sorted in scheduler if not running async // we need to sort them now to make sure they fire in correct // order subs.sort((a, b) => a.id - b.id) } for (let i = 0, l = subs.length; i \u003C l; i++) { subs[i].update() // Notify the Watcher to update the view when data changes. } } } Implementation of the Watcher //",{"type":17,"tag":74,"props":405,"children":408},{"href":406,"rel":407},"https://github.com/vuejs/vue/blob/v2.6.14/src/core/observer/watcher.js",[78],[409],{"type":23,"value":406},{"type":23,"value":411}," /** * Subscriber interface. * Will be called when a dependency changes. */ update () { // The Watcher updates the view. /* istanbul ignore else */ if (this.lazy) { this.dirty = true } else if (this.sync) { this.run() } else { queueWatcher(this) } } 04 Summary I would like to thank the MindSpore community for providing this opportunity. This is my first time participating in an open source project, and through this experience, I have learned about the development process of a project and how members in an open source community collaborate to develop and maintain a project. Additionally, this open source experience has taught me how beginners can participate in open source and how to correctly submit pull requests. I will continue to contribute my own strength to open source in the future.",{"title":7,"searchDepth":413,"depth":413,"links":414},4,[],"markdown","content:news:en:2760.md","content","news/en/2760.md","news/en/2760","md",1776506045765]