[{"data":1,"prerenderedAt":837},["ShallowReactive",2],{"content-query-TyP3gzVfTC":3},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"title":8,"description":9,"date":10,"cover":11,"type":12,"category":13,"body":14,"_type":831,"_id":832,"_source":833,"_file":834,"_stem":835,"_extension":836},"/technology-blogs/zh/1695","zh",false,"","【MindSpore易点通】常用性能调优方法经验总结","MindSpore提供了一种自动数据调优的工具Dataset AutoTune，用于在训练过程中根据环境资源的情况自动调整数据处理管道的并行度，最大化利用系统资源加速数据处理管道的处理速度。","2022-08-12","https://obs-mindspore-file.obs.cn-north-4.myhuaweicloud.com/file/2022/08/15/3cb3f58c45d0480f8ceffe23e80fd61a.png","technology-blogs","实践",{"type":15,"children":16,"toc":818},"root",[17,25,31,47,52,57,62,67,72,76,81,86,91,96,101,105,109,114,118,123,128,133,138,148,163,168,173,178,183,188,197,211,216,221,225,230,235,240,245,249,253,258,267,281,286,295,300,314,319,324,329,334,339,344,354,363,377,382,387,391,399,404,409,414,419,424,429,434,439,444,452,456,460,464,468,472,476,481,485,492,497,501,506,510,514,519,523,530,534,538,542,546,550,559,564,578,583,588,593,598,603,608,613,618,622,627,632,637,641,646,650,655,659,664,669,673,677,681,685,689,693,698,702,709,713,717,721,725,729,734,741,745,749,753,757,761,769,783,799,813],{"type":18,"tag":19,"props":20,"children":22},"element","h1",{"id":21},"mindspore易点通常用性能调优方法经验总结",[23],{"type":24,"value":8},"text",{"type":18,"tag":26,"props":27,"children":28},"p",{},[29],{"type":24,"value":30},"本文给大家介绍几种常用的性能调优方法。",{"type":18,"tag":32,"props":33,"children":35},"h2",{"id":34},"调整数据处理进程数",[36],{"type":18,"tag":37,"props":38,"children":39},"strong",{},[40],{"type":18,"tag":37,"props":41,"children":42},{},[43],{"type":18,"tag":37,"props":44,"children":45},{},[46],{"type":24,"value":34},{"type":18,"tag":26,"props":48,"children":49},{},[50],{"type":24,"value":51},"MindSpore Data中的某些算子接收num_parallel_workers参数，该参数设置了算子使用的线程数。根据物理内核的数量和目标系统的负载，增加管道中num_parallel_workers的值，可以提高性能。对于任何包含计算密集型Tensor运算（比如Decode）的Map算子而言，尤其如此。",{"type":18,"tag":26,"props":53,"children":54},{},[55],{"type":24,"value":56},"使用默认数据处理进程数（为1）：",{"type":18,"tag":26,"props":58,"children":59},{},[60],{"type":24,"value":61},"if do_train:",{"type":18,"tag":26,"props":63,"children":64},{},[65],{"type":24,"value":66},"cifar_ds = ds.Cifar10Dataset(dataset_dir=data_home,",{"type":18,"tag":26,"props":68,"children":69},{},[70],{"type":24,"value":71},"shuffle=True, usage='train')else:",{"type":18,"tag":26,"props":73,"children":74},{},[75],{"type":24,"value":66},{"type":18,"tag":26,"props":77,"children":78},{},[79],{"type":24,"value":80},"shuffle=False, usage='test')",{"type":18,"tag":26,"props":82,"children":83},{},[84],{"type":24,"value":85},"cifar_ds = cifar_ds.map(operations=transform_label, input_columns=\"label\")",{"type":18,"tag":26,"props":87,"children":88},{},[89],{"type":24,"value":90},"cifar_ds = cifar_ds.map(operations=transform_data, input_columns=\"image\")",{"type":18,"tag":26,"props":92,"children":93},{},[94],{"type":24,"value":95},"cifar_ds = cifar_ds.batch(batch_size, drop_remainder=True)",{"type":18,"tag":26,"props":97,"children":98},{},[99],{"type":24,"value":100},"调整数据处理进程数为2:",{"type":18,"tag":26,"props":102,"children":103},{},[104],{"type":24,"value":61},{"type":18,"tag":26,"props":106,"children":107},{},[108],{"type":24,"value":66},{"type":18,"tag":26,"props":110,"children":111},{},[112],{"type":24,"value":113},"num_parallel_workers=2, shuffle=True, usage='train')else:",{"type":18,"tag":26,"props":115,"children":116},{},[117],{"type":24,"value":66},{"type":18,"tag":26,"props":119,"children":120},{},[121],{"type":24,"value":122},"num_parallel_workers=2, shuffle=False, usage='test')",{"type":18,"tag":26,"props":124,"children":125},{},[126],{"type":24,"value":127},"cifar_ds = cifar_ds.map(operations=transform_label, num_parallel_workers=2, python_multiprocessing=True, input_columns=\"label\")",{"type":18,"tag":26,"props":129,"children":130},{},[131],{"type":24,"value":132},"cifar_ds = cifar_ds.map(operations=transform_data, num_parallel_workers=2, python_multiprocessing=True, python_multiprocessing=True, input_columns=\"image\")",{"type":18,"tag":26,"props":134,"children":135},{},[136],{"type":24,"value":137},"cifar_ds = cifar_ds.batch(batch_size, num_parallel_workers=2, drop_remainder=True)",{"type":18,"tag":26,"props":139,"children":140},{},[141,146],{"type":18,"tag":37,"props":142,"children":143},{},[144],{"type":24,"value":145},"运行后****性能对比",{"type":24,"value":147},"：使用默认数据处理进程数：2200 imgs/sec ；调整数据处理进程数为2：2300 imgs/sec",{"type":18,"tag":32,"props":149,"children":151},{"id":150},"使用mindrecord格式加载数据",[152],{"type":18,"tag":37,"props":153,"children":154},{},[155],{"type":18,"tag":37,"props":156,"children":157},{},[158],{"type":18,"tag":37,"props":159,"children":160},{},[161],{"type":24,"value":162},"使用MindRecord格式加载数据",{"type":18,"tag":26,"props":164,"children":165},{},[166],{"type":24,"value":167},"目前MindSpore Data支持的特定格式数据集为：MindRecord。使用MindRecord格式的加载数据性能更优。",{"type":18,"tag":26,"props":169,"children":170},{},[171],{"type":24,"value":172},"MindRecord数据加载流程：",{"type":18,"tag":26,"props":174,"children":175},{},[176],{"type":24,"value":177},"import mindspore.dataset as ds",{"type":18,"tag":26,"props":179,"children":180},{},[181],{"type":24,"value":182},"CV_FILE_NAME = \"./cifar10.mindrecord\"",{"type":18,"tag":26,"props":184,"children":185},{},[186],{"type":24,"value":187},"cifar_ds = ds.MindDataset(dataset_file=CV_FILE_NAME，columns_list=[\"data\",\"label\"], shuffle=True)",{"type":18,"tag":26,"props":189,"children":190},{},[191,195],{"type":18,"tag":37,"props":192,"children":193},{},[194],{"type":24,"value":145},{"type":24,"value":196},"： 自定义数据集加载cifar10：850 imgs/sec；MindRecord格式加载cifar10：2200 imgs/sec",{"type":18,"tag":32,"props":198,"children":200},{"id":199},"加载数据集时shuffle",[201],{"type":18,"tag":37,"props":202,"children":203},{},[204],{"type":18,"tag":37,"props":205,"children":206},{},[207],{"type":18,"tag":37,"props":208,"children":209},{},[210],{"type":24,"value":199},{"type":18,"tag":26,"props":212,"children":213},{},[214],{"type":24,"value":215},"数据集加载时shuffle，算子可以在生成输出Tensor之前对数据进行内部shuffle。与在管道中使用显式shuffle算子相比，这种内部shuffle通常会带来更好的性能。",{"type":18,"tag":26,"props":217,"children":218},{},[219],{"type":24,"value":220},"管道中使用显式shuffle：",{"type":18,"tag":26,"props":222,"children":223},{},[224],{"type":24,"value":177},{"type":18,"tag":26,"props":226,"children":227},{},[228],{"type":24,"value":229},"DATA_DIR = \"./cifar-10-batches-bin/\"",{"type":18,"tag":26,"props":231,"children":232},{},[233],{"type":24,"value":234},"cifar_ds = ds.Cifar10Dataset(DATA_DIR, usage='train')",{"type":18,"tag":26,"props":236,"children":237},{},[238],{"type":24,"value":239},"cifar_ds = cifar_ds.shuffle(buffer_size=10000)",{"type":18,"tag":26,"props":241,"children":242},{},[243],{"type":24,"value":244},"加载数据集时shuffle：",{"type":18,"tag":26,"props":246,"children":247},{},[248],{"type":24,"value":177},{"type":18,"tag":26,"props":250,"children":251},{},[252],{"type":24,"value":229},{"type":18,"tag":26,"props":254,"children":255},{},[256],{"type":24,"value":257},"cifar_ds = ds.Cifar10Dataset(DATA_DIR, shuffle=True, usage='train')",{"type":18,"tag":26,"props":259,"children":260},{},[261,265],{"type":18,"tag":37,"props":262,"children":263},{},[264],{"type":24,"value":145},{"type":24,"value":266},"：本样例未见明显性能收益",{"type":18,"tag":32,"props":268,"children":270},{"id":269},"混合精度",[271],{"type":18,"tag":37,"props":272,"children":273},{},[274],{"type":18,"tag":37,"props":275,"children":276},{},[277],{"type":18,"tag":37,"props":278,"children":279},{},[280],{"type":24,"value":269},{"type":18,"tag":26,"props":282,"children":283},{},[284],{"type":24,"value":285},"混合精度训练方法是通过混合使用单精度和半精度数据格式来加速深度神经网络训练的过程，同时保持了单精度训练所能达到的网络精度。混合精度训练能够加速计算过程，同时减少内存使用和存取，并使得在特定的硬件上可以训练更大的模型或batch size。",{"type":18,"tag":26,"props":287,"children":288},{},[289,293],{"type":18,"tag":37,"props":290,"children":291},{},[292],{"type":24,"value":145},{"type":24,"value":294},"：高阶API: 2200 imgs/sec ；高阶API混合精度: 3300 imgs/sec",{"type":18,"tag":26,"props":296,"children":297},{},[298],{"type":24,"value":299},"低阶API: 2000 imgs/sec ；低阶API混合精度: 3200 imgs/sec",{"type":18,"tag":32,"props":301,"children":303},{"id":302},"数据下沉",[304],{"type":18,"tag":37,"props":305,"children":306},{},[307],{"type":18,"tag":37,"props":308,"children":309},{},[310],{"type":18,"tag":37,"props":311,"children":312},{},[313],{"type":24,"value":302},{"type":18,"tag":26,"props":315,"children":316},{},[317],{"type":24,"value":318},"采用数据集的下沉模式，即训练计算下沉到硬件平台中执行，数据下沉可以优化训练性能。",{"type":18,"tag":26,"props":320,"children":321},{},[322],{"type":24,"value":323},"将Model.train接口中dataset_sink_mode 值设为True，即可采用数据下沉模式。",{"type":18,"tag":26,"props":325,"children":326},{},[327],{"type":24,"value":328},"数据未下沉：",{"type":18,"tag":26,"props":330,"children":331},{},[332],{"type":24,"value":333},"model.train(..., dataset_sink_mode=False, ...)",{"type":18,"tag":26,"props":335,"children":336},{},[337],{"type":24,"value":338},"数据下沉：",{"type":18,"tag":26,"props":340,"children":341},{},[342],{"type":24,"value":343},"model.train(..., dataset_sink_mode=True, sink_size=steps_per_epoch_train)",{"type":18,"tag":26,"props":345,"children":346},{},[347,352],{"type":18,"tag":37,"props":348,"children":349},{},[350],{"type":24,"value":351},"注",{"type":24,"value":353},"：低阶API不支持数据下沉，若想实现数据下沉请使用Model.train接口进行训练。",{"type":18,"tag":26,"props":355,"children":356},{},[357,361],{"type":18,"tag":37,"props":358,"children":359},{},[360],{"type":24,"value":145},{"type":24,"value":362},"：数据未下沉：2000 imgs/sec；数据下沉：2200 imgs/sec",{"type":18,"tag":32,"props":364,"children":366},{"id":365},"避免c_transform和py_transform混用",[367],{"type":18,"tag":37,"props":368,"children":369},{},[370],{"type":18,"tag":37,"props":371,"children":372},{},[373],{"type":18,"tag":37,"props":374,"children":375},{},[376],{"type":24,"value":365},{"type":18,"tag":26,"props":378,"children":379},{},[380],{"type":24,"value":381},"c_transform是在C++内维护buffer管理，py_transform是在python内维护buffer管理。因为python和C++切换的性能成本，建议不要混用算子，否则会降低训练性能。",{"type":18,"tag":26,"props":383,"children":384},{},[385],{"type":24,"value":386},"c_transform和py_transform混用：",{"type":18,"tag":26,"props":388,"children":389},{},[390],{"type":24,"value":61},{"type":18,"tag":26,"props":392,"children":393},{},[394],{"type":18,"tag":37,"props":395,"children":396},{},[397],{"type":24,"value":398},"# Transformation on train data",{"type":18,"tag":26,"props":400,"children":401},{},[402],{"type":24,"value":403},"transform_data = py_trans.Compose([",{"type":18,"tag":26,"props":405,"children":406},{},[407],{"type":24,"value":408},"CV.RandomCrop((32, 32), (4, 4, 4, 4)),",{"type":18,"tag":26,"props":410,"children":411},{},[412],{"type":24,"value":413},"py_vision.ToPIL(),",{"type":18,"tag":26,"props":415,"children":416},{},[417],{"type":24,"value":418},"py_vision.RandomHorizontalFlip(),",{"type":18,"tag":26,"props":420,"children":421},{},[422],{"type":24,"value":423},"CV.Rescale(rescale, shift),",{"type":18,"tag":26,"props":425,"children":426},{},[427],{"type":24,"value":428},"CV.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),",{"type":18,"tag":26,"props":430,"children":431},{},[432],{"type":24,"value":433},"CV.HWC2CHW()",{"type":18,"tag":26,"props":435,"children":436},{},[437],{"type":24,"value":438},"])",{"type":18,"tag":26,"props":440,"children":441},{},[442],{"type":24,"value":443},"else:",{"type":18,"tag":26,"props":445,"children":446},{},[447],{"type":18,"tag":37,"props":448,"children":449},{},[450],{"type":24,"value":451},"# Transformation on validation data",{"type":18,"tag":26,"props":453,"children":454},{},[455],{"type":24,"value":403},{"type":18,"tag":26,"props":457,"children":458},{},[459],{"type":24,"value":423},{"type":18,"tag":26,"props":461,"children":462},{},[463],{"type":24,"value":428},{"type":18,"tag":26,"props":465,"children":466},{},[467],{"type":24,"value":433},{"type":18,"tag":26,"props":469,"children":470},{},[471],{"type":24,"value":438},{"type":18,"tag":26,"props":473,"children":474},{},[475],{"type":24,"value":90},{"type":18,"tag":26,"props":477,"children":478},{},[479],{"type":24,"value":480},"c_transform和py_transform未混用：",{"type":18,"tag":26,"props":482,"children":483},{},[484],{"type":24,"value":61},{"type":18,"tag":26,"props":486,"children":487},{},[488],{"type":18,"tag":37,"props":489,"children":490},{},[491],{"type":24,"value":398},{"type":18,"tag":26,"props":493,"children":494},{},[495],{"type":24,"value":496},"transform_data = C.Compose([",{"type":18,"tag":26,"props":498,"children":499},{},[500],{"type":24,"value":408},{"type":18,"tag":26,"props":502,"children":503},{},[504],{"type":24,"value":505},"CV.RandomHorizontalFlip(),",{"type":18,"tag":26,"props":507,"children":508},{},[509],{"type":24,"value":423},{"type":18,"tag":26,"props":511,"children":512},{},[513],{"type":24,"value":428},{"type":18,"tag":26,"props":515,"children":516},{},[517],{"type":24,"value":518},"CV.HWC2CHW()])",{"type":18,"tag":26,"props":520,"children":521},{},[522],{"type":24,"value":443},{"type":18,"tag":26,"props":524,"children":525},{},[526],{"type":18,"tag":37,"props":527,"children":528},{},[529],{"type":24,"value":451},{"type":18,"tag":26,"props":531,"children":532},{},[533],{"type":24,"value":496},{"type":18,"tag":26,"props":535,"children":536},{},[537],{"type":24,"value":423},{"type":18,"tag":26,"props":539,"children":540},{},[541],{"type":24,"value":428},{"type":18,"tag":26,"props":543,"children":544},{},[545],{"type":24,"value":518},{"type":18,"tag":26,"props":547,"children":548},{},[549],{"type":24,"value":90},{"type":18,"tag":26,"props":551,"children":552},{},[553,557],{"type":18,"tag":37,"props":554,"children":555},{},[556],{"type":24,"value":145},{"type":24,"value":558},"：c_transform和py_transform混用：1100 imgs/sec；",{"type":18,"tag":26,"props":560,"children":561},{},[562],{"type":24,"value":563},"c_transform和py_transform未混用：2200 imgs/sec",{"type":18,"tag":32,"props":565,"children":567},{"id":566},"多map合并单map",[568],{"type":18,"tag":37,"props":569,"children":570},{},[571],{"type":18,"tag":37,"props":572,"children":573},{},[574],{"type":18,"tag":37,"props":575,"children":576},{},[577],{"type":24,"value":566},{"type":18,"tag":26,"props":579,"children":580},{},[581],{"type":24,"value":582},"数据预处理时，Map算子可以接收Tensor算子列表，并将按顺序应用所有的这些算子。与为每个Tensor算子使用单独的Map算子相比，可以获得更好的性能。",{"type":18,"tag":26,"props":584,"children":585},{},[586],{"type":24,"value":587},"多map数据预处理：",{"type":18,"tag":26,"props":589,"children":590},{},[591],{"type":24,"value":592},"randomcrop_op = CV.RandomCrop((32, 32), (4, 4, 4, 4))",{"type":18,"tag":26,"props":594,"children":595},{},[596],{"type":24,"value":597},"randomhorizontalflip_op = CV.RandomHorizontalFlip()",{"type":18,"tag":26,"props":599,"children":600},{},[601],{"type":24,"value":602},"rescale_op = CV.Rescale(rescale, shift)",{"type":18,"tag":26,"props":604,"children":605},{},[606],{"type":24,"value":607},"normalize_op = CV.Normalize((0.4914, 0.4822, 0.4465),",{"type":18,"tag":26,"props":609,"children":610},{},[611],{"type":24,"value":612},"(0.2023, 0.1994, 0.2010))",{"type":18,"tag":26,"props":614,"children":615},{},[616],{"type":24,"value":617},"hwc2chw_op = CV.HWC2CHW()",{"type":18,"tag":26,"props":619,"children":620},{},[621],{"type":24,"value":61},{"type":18,"tag":26,"props":623,"children":624},{},[625],{"type":24,"value":626},"cifar_ds = cifar_ds.map(operations=[randomcrop_op],",{"type":18,"tag":26,"props":628,"children":629},{},[630],{"type":24,"value":631},"input_columns=\"image\")",{"type":18,"tag":26,"props":633,"children":634},{},[635],{"type":24,"value":636},"cifar_ds = cifar_ds.map(operations=[randomhorizontalflip_op],",{"type":18,"tag":26,"props":638,"children":639},{},[640],{"type":24,"value":631},{"type":18,"tag":26,"props":642,"children":643},{},[644],{"type":24,"value":645},"cifar_ds = cifar_ds.map(operations=[rescale_op],",{"type":18,"tag":26,"props":647,"children":648},{},[649],{"type":24,"value":631},{"type":18,"tag":26,"props":651,"children":652},{},[653],{"type":24,"value":654},"cifar_ds = cifar_ds.map(operations=[normalize_op],",{"type":18,"tag":26,"props":656,"children":657},{},[658],{"type":24,"value":631},{"type":18,"tag":26,"props":660,"children":661},{},[662],{"type":24,"value":663},"cifar_ds = cifar_ds.map(operations=[hwc2chw_op],",{"type":18,"tag":26,"props":665,"children":666},{},[667],{"type":24,"value":668},"input_columns=\"image\")else:",{"type":18,"tag":26,"props":670,"children":671},{},[672],{"type":24,"value":645},{"type":18,"tag":26,"props":674,"children":675},{},[676],{"type":24,"value":631},{"type":18,"tag":26,"props":678,"children":679},{},[680],{"type":24,"value":654},{"type":18,"tag":26,"props":682,"children":683},{},[684],{"type":24,"value":631},{"type":18,"tag":26,"props":686,"children":687},{},[688],{"type":24,"value":663},{"type":18,"tag":26,"props":690,"children":691},{},[692],{"type":24,"value":631},{"type":18,"tag":26,"props":694,"children":695},{},[696],{"type":24,"value":697},"合并成单map数据预处理：",{"type":18,"tag":26,"props":699,"children":700},{},[701],{"type":24,"value":61},{"type":18,"tag":26,"props":703,"children":704},{},[705],{"type":18,"tag":37,"props":706,"children":707},{},[708],{"type":24,"value":398},{"type":18,"tag":26,"props":710,"children":711},{},[712],{"type":24,"value":496},{"type":18,"tag":26,"props":714,"children":715},{},[716],{"type":24,"value":408},{"type":18,"tag":26,"props":718,"children":719},{},[720],{"type":24,"value":505},{"type":18,"tag":26,"props":722,"children":723},{},[724],{"type":24,"value":423},{"type":18,"tag":26,"props":726,"children":727},{},[728],{"type":24,"value":428},{"type":18,"tag":26,"props":730,"children":731},{},[732],{"type":24,"value":733},"CV.HWC2CHW()])else:",{"type":18,"tag":26,"props":735,"children":736},{},[737],{"type":18,"tag":37,"props":738,"children":739},{},[740],{"type":24,"value":451},{"type":18,"tag":26,"props":742,"children":743},{},[744],{"type":24,"value":496},{"type":18,"tag":26,"props":746,"children":747},{},[748],{"type":24,"value":423},{"type":18,"tag":26,"props":750,"children":751},{},[752],{"type":24,"value":428},{"type":18,"tag":26,"props":754,"children":755},{},[756],{"type":24,"value":518},{"type":18,"tag":26,"props":758,"children":759},{},[760],{"type":24,"value":90},{"type":18,"tag":26,"props":762,"children":763},{},[764,768],{"type":18,"tag":37,"props":765,"children":766},{},[767],{"type":24,"value":145},{"type":24,"value":266},{"type":18,"tag":32,"props":770,"children":772},{"id":771},"融合算子",[773],{"type":18,"tag":37,"props":774,"children":775},{},[776],{"type":18,"tag":37,"props":777,"children":778},{},[779],{"type":18,"tag":37,"props":780,"children":781},{},[782],{"type":24,"value":771},{"type":18,"tag":26,"props":784,"children":785},{},[786,788,797],{"type":24,"value":787},"MindSpore Data提供某些融合算子，这些算子将两个或多个算子的功能聚合到一个算子中。 与它们各自组件的流水线相比，这种融合算子提供了更好的性能。一个很好的融合算子是RandomCropDecodeResizeOp，它执行解码，然后对任意给定的Tensor进行随机裁剪和大小调整。用户可以查看算子",{"type":18,"tag":789,"props":790,"children":794},"a",{"href":791,"rel":792},"https://www.mindspore.cn/docs/zh-CN/master/api_python/mindspore.dataset.vision.html",[793],"nofollow",[795],{"type":24,"value":796},"API文档",{"type":24,"value":798},"查看是否有相应融合算子替代现有算子，以获得更好性能。",{"type":18,"tag":32,"props":800,"children":802},{"id":801},"自动数据加速",[803],{"type":18,"tag":37,"props":804,"children":805},{},[806],{"type":18,"tag":37,"props":807,"children":808},{},[809],{"type":18,"tag":37,"props":810,"children":811},{},[812],{"type":24,"value":801},{"type":18,"tag":26,"props":814,"children":815},{},[816],{"type":24,"value":817},"MindSpore提供了一种自动数据调优的工具——Dataset AutoTune，用于在训练过程中根据环境资源的情况自动调整数据处理管道的并行度，最大化利用系统资源加速数据处理管道的处理速度。在整个训练的过程中，Dataset AutoTune模块会持续检测当前训练性能瓶颈处于数据侧还是网络侧。如果检测到瓶颈在数据侧，则将进一步对数据处理管道中的各个算子（如GeneratorDataset、map、batch此类数据算子）进行参数调整。",{"title":7,"searchDepth":819,"depth":819,"links":820},4,[821,823,824,825,826,827,828,829,830],{"id":34,"depth":822,"text":34},2,{"id":150,"depth":822,"text":162},{"id":199,"depth":822,"text":199},{"id":269,"depth":822,"text":269},{"id":302,"depth":822,"text":302},{"id":365,"depth":822,"text":365},{"id":566,"depth":822,"text":566},{"id":771,"depth":822,"text":771},{"id":801,"depth":822,"text":801},"markdown","content:technology-blogs:zh:1695.md","content","technology-blogs/zh/1695.md","technology-blogs/zh/1695","md",1776506114953]