zoukankan      html  css  js  c++  java
  • MindSpore技术理解(下)

    MindSpore技术理解(下)

    4 GraphEngine

    由于深度学习算法需要进行大量的计算,很多公司都设计了自己的深度学习专用处理器(如谷歌的张量处理器、阿里巴巴的含光等),华为也发布了自主设计的神经网络处理单元(Neural Processing Unit,NPU)——昇腾系列芯片。可以借助 GE 在 GPU、CPU、昇腾系列芯片上操作 MindSpore 定义的模型。 如图 1 所示,GE 位于 ME 和设备之间。GE 将 ME 的输出数据流图作为输入,在 GE 内部执行某些 图处理操作,以实现昇腾系列芯片的高效操作。GE 可以直接访问所有底层组件,负责图形管理、资 源分配和设备交互。

    1. 前端交互

    GE 内部初始化一个会话,与 ME 的会话通信,以获取待添加的图。为了避免直接访问前端的数据结构,在发送前使用 protobuf 实现序列化。GE 内部采用协同响应的反序列化,这一过程 保证了数据完全解耦。

    2. 图编译器

    GE 最基本也是最重要的功能是图形管理,包括图形处理和图形生命周期管理。GE 内执行一系列图形处理操作,以实现对设备的有效操作。

    首先,对变量和特征映射的所有形状进行推断,以便以后进行内存分配。设备中的物理计算核在 GE 中对应不同的抽象引擎,根据引擎是否支 持算子以及引擎上的成本(有的算子只能在特定的引擎上运行,所以分配引擎时要看引擎是否 支持算子,如果多个引擎都支持该算子,则看每个引擎上的成本),图中的每一个算子都被分配 到一个最优的引擎。

    然后,根据分配的引擎,将整个图分解为若干个子图。某些算子被添加到 子图中,作为图边标记。这样的一个分区使以后的优化和编译更加高效。

    根据分配的不同引擎,每个子图采用不同的优化过程。该方法删除了部分冗余算子,将部分算子组合为一个大算子,进一步减少了运算量。专门设计了一种新颖的数据布局格式,以便 在昇腾系列芯片上实现更快的操作。将原始张量沿 C 轴切分为若干 C0(例如 C0=16),并将其 转换为如 4 2.图 6 所示的 5D 格式,从而确保更快地在昇腾系列芯片上获取硬件。

     

    3. 执行和插件

    图形编译和资源分配是在高度优化的图形上完成的。GE 在考虑内存复用的基础上进行内存申请,同时根据图内信息进行流和同步信号的分配。事件作为不同流之间的同步信号,保证正确的任务执行顺序。每个算子被编译为一个或多个任务,同一个算子编译出来的任务被绑定到同一条流上,不同流上的任务可以并行执行。根据不同节点之间的控制依赖关系,可以导出图中所有节点的时序关系。不同流可以并行执行,同一流中的算子之间串行操作。因此,根据顺序关系信息选择适当的流分配策略,从而保证节点之间的完全并行计算,而且不存在控制依赖关系。算子加载到对应的引擎上执行。GE 还提供 GE Plugins 作为外部插件,以便扩展 GE 的特 性。GE 只定义了外部插件模块的注册接口,具体功能在每个插件中实现,这样的设计保证了 GE 的可行性和灵活性。

    5 MindData

    5.1 数据处理

    数据处理是一个单独的异步流水线,它为张量馈入模型做好准备。在流水线内,数据被组织成一系 列具有不同列的行,所有列都用列名标识,并且可以独立访问。流水线总是从一个源数据集算子开 始,该算子从磁盘(如 MindDataset)读取数据,并包含选择 shuffling 和 sharding 策略的标记。为 了访问流水线中的数据,可使用迭代器(Python 访问)或设备队列(直接发送到加速器设备)。

    数据处理的体系结构本质上是流水线且并行的,管道的运行默认是异步的,但用户也可以在图中插 入同步点,以便流水线算子能够实时反馈循环。未来,流水线将进行动态调整,以充分利用所有可 用的资源,包括用于图像处理的硬件加速器或用于缓存的可用内存,用户只需配置默认参数以获得 良好的性能,而无须进行手动调优。

    为了让用户实现快速迁移,数据处理支持用户已有的 Python 数据增强作为自定义算子以 pyfunc 方 式接入,同时现有的 Python 数据集类可以作为参数传递给 GeneratorDataset 接入。不断涌现的新 网络对数据处理的灵活性提出了新要求。数据处理支持使用用户自定义的函数(或调度)来更改参 数,例如 mini-batch 大小;还支持用户对整个 mini-batch 进行自定义转换,以进行 mini-batch 级的图像大小或多行操作(如图像混合)。为了获得更多样的增强,每个样本的增强可以从一个数据增强 操作列表中随机选择。另外,可以通过外部搜索(即 Fast AutoAugment)在候选数据增强操作列表 中进行选择,最近关于 randomAugment 和 uniformAugment 的研究表明,对很多数据集来说,只 随机从大量数据增强策略中选择合适的,不采用耗费大量搜索时间的自动数据增强方法,同样能获 得很好的结果。在训练中收集的度量的反馈(如 loss)也可以传回至数据集,以在数据处理中执行 动态调整,如 Adversrial AutoAugment 中所示。

    5.2 MindRecord MindRecord
    数据集格式将用户的训练数据按不同类型、不同页面进行存储,建立轻量化、高效的索引,并提供一套接口,方便用户将训练数据转换成 MindRecord 格式,然后使用 MindDataset 将训 练数据读入数据集。同时,可以快速从数据集读取重要的元数据(即数据集大小或数据布局)以提 高性能或简化用户访问。MindRecord 能够支持小块数据的高效顺序 I/O,还可以根据用例需要支持高效的随机行访问和下沉过滤。随着新用例的出现,进一步优化的功能会下沉到该数据集。

    5.3 MindInsight MindInsight 提供训练看板、溯源、性能分析和调试器的功能。这些功能可以帮助开发者在训练模型 的过程中发现模型训练过程中出现的偏差,发现超参、数据增强等因素的影响,并对模型进行调试 和性能分析。通过 MindInsight,开发者可以更好地观察和理解训练过程,这样可以提升模型优化效率并优化开发者体验。

    MindInsight 架构如 5.3 图 7 所示。

    MindInsight 以模型训练中生成的日志文件作为输入。通过文件解析、信息提取、数据缓存、图表绘 制等一系列过程,将二进制训练信息转换成易于理解的图表,并展示在网页上。

    5.3.1 训练看板 MindInsight

    支持训练过程可视化。训练看板支持在页面上查看训练过程。训练看板包括训练标量信 息、参数分布图、计算图、数据图、数据抽样等模块。 训练看板是 MindInsight 在训练过程呈现方式上的创新。通过在一个页面中集成多种类型的数据,用 户只需要打开训练看板就能概览训练情况。

    5.3.1 图 8 展示了训练看板的一个示例。

     

    5.3.2 溯源 MindInsight 还支持溯源可视化。

    通过将多个训练的溯源信息整合到表格和图形中,用户可以轻松选 择最优的数据处理流水线和超参设置。溯源可视化包括模型溯源可视化和数据溯源可视化。模型溯 源函数可以记录模型训练的关键参数,如损失函数、优化器、迭代次数、精度等。MindInsight 中显示多次训练的超参和评估指标,帮助用户选择最优超参。未来,将逐步引入辅助超参推荐,帮助用 户快速优化超参。

    图 9 展示了模型溯源可视化的一个示例。数据溯源可视化可以记录每次模型训练的数据处理流水线。多次训练的数据处理模式显示在 MindInsight 上,帮助用户选择最优的数据处理流水线。

    图 10 展示了数据溯源可视化的一个示例。

     

    5.3.3 性能分析

    为了满足工程师对神经网络性能优化的要求,我们设计并实现了性能分析工具。它可以打开 MindSpore 神经网络的执行过程,收集各算子的时间、内存等数据。MindInsight 会进一步对性能数 据进行整理、分析,呈现多维度、多层次的性能分析结果。这为神经网络性能优化提供了方向。

    性能数据展示维度包括:

    1. 迭代轨迹 迭代轨迹将神经网络的执行分解为多个阶段,包括数据读取、前向和反向计算、Allreduce 等, 工程师可以快速发现哪个阶段是目前的性能瓶颈。

    2. 算子性能 算子性能将聚合并整理算子执行时间的数据,这样工程师可以很容易找出耗时的算子。

    3. 时间轴 时间轴可以显示芯片侧执行流和执行任务的状态,帮助工程师进行细粒度的性能分析。

    4. MindData Profiling 可以帮助用户定位和分析训练数据获取过程中的瓶颈,工程师可以通过提高瓶颈算子的线程数 等方法来提高性能。

    5.3.4 调试器

    神经网络训练中经常出现数值误差情况,如无穷大等,用户希望分析训练无法收敛的原因。但是, 由于计算被封装为黑盒,以图的方式执行,工程师很难定位其中的错误。MindInsight 调试器是图模 式下训练调试的工具,用户可以在训练过程中查看图的内部结构以及节点的输入/输出,例如查看一 个张量的值,查看图中的节点对应的 Python 代码等。此外,用户还可以选择一组节点设置条件断点, 实时监控节点的计算结果。

    6 MindArmour

    6.1 对抗性攻击防御

    对抗性攻击[26,27]对机器学习模型安全的威胁日益严重。攻击者可以通过向原始样本添加人类不易感 知的小扰动来欺骗机器学习模型[28,29]。为了防御对抗性攻击,MA 提供了攻击(对抗样本生成)、 防御(对抗样本检测和对抗性训练)、评估(模型鲁棒性评估和可视化)等功能。 给定模型和输入数据,攻击模块提供简单的 API,能够在黑盒和白盒攻击场景下生成相应的对抗样 本。这些生成的对抗样本被输入防御模块,以提高机器学习模型的泛化能力和鲁棒性。防御模块还 实现了多种检测算法,能够根据恶意内容或攻击行为来区分对抗样本和正常样本。评估模块提供了 多种评估指标,开发者能够轻松地评估和可视化模型的鲁棒性。

    6.2 隐私保护人工智能 隐私保护也是人工智能应用的一个重要课题。MA 考虑了机器学习中的隐私保护问题,并提供了相 应的隐私保护功能。针对已训练模型可能会泄露训练数据集中的敏感信息问题[30,31],MA 实现了一 系列差分隐私优化器,自动将噪声加入反向计算生成的梯度中,从而为已训练模型提供差分隐私保 障。特别地,优化器根据训练过程自适应地加入噪声,能够在相同的隐私预算下实现更好的模型可 用性。同时提供了监测模块,能够对训练过程中的隐私预算消耗进行动态监测。用户可以像使用普 通优化器一样使用这些差分隐私优化器。

    7 端云协同架构

    MindSpore 旨在构建一个从端侧到云侧全场景覆盖的人工智能框架,将支持“端云”协同能力,包 括模型优化、端侧训练和推理、联邦学习等过程,如图 11 所示。

     

    1. 模型生成与优化工具包 移动和边缘设备通常资源有限,如电源和内存。为了帮助用户利用有限的资源部署模型, MindSpore 将支持一系列优化技术,如模型自适应生成、量化策略等,如图 11 左侧所示。模 型自适应生成是指应用神经架构搜索(Neural Architecture Search,NAS[32])技术来生成在不 同设备下时延、精度、模型大小均满足需求的模型。量化策略是指通过以更少位数的数据类型 来近似表示 32 位有限范围浮点数据类型的过程,MindSpore 支持训练后量化和量化感知训练。

    2. 端侧训练和联邦学习 虽然在大型数据集上训练的深度学习模型在一定程度上是通用的,但是在某些场景中,这些模 型仍然不适用于用户自己的数据或个性化任务。 MindSpore 计划提供端侧训练方案,允许用户训练自己的个性化模型,或对设备上现有的模型 进行微调,同时避免了数据隐私、带宽限制和网络连接等问题。端侧将提供多种训练策略,如 初始化训练策略、迁移学习、增量学习等。MindSpore 还将支持联邦学习,通过向云侧发送模 型更新/梯度来共享不同的数据,如图 11 所示。基于联邦学习,模型可以学习更多的通用知识。

    3. 移动和边缘设备部署 MindSpore 提供轻量级的计算引擎,支持模型在设备上高效执行。在将预先训练好的模型部署 到设备侧时,通常需要进行模型转换。然而,这个过程可能导致性能降低和精度损失。在 MindSpore 中,端侧推理模式能够兼容云上训练好的模型,因此,在设备上部署已经训练好的 模型时,无须进行转换,这样避免了潜在的性能损失。此外,MindSpore 还内置了针对设备的 各种自动优化,例如图和算子融合、精细复杂的内存管理、硬件加速等,如图 11 右侧所示。

    8 评估

    在本节中,我们评估了 MindSpore 在自动并行方面的性能,还在华为昇腾系列芯片集群上进行了实 验,并与当前主流的深度学习框架进行了性能对比。结果表明,我们的系统具有以下特点:(

    1)高 通量;

    (2)加速比随着集群的增加保持稳定。此外,我们提供了几种模型的推理性能,并获得了比 主流的深度学习框架更好的性能。

    8.1 自动并行 我们在一个有 8 台设备的昇腾服务器上进行了实验。使用标准的 ResNet50,分别在原始数据并行 和自动并行下训练。原始数据并行和自动并行的比较结果如图 12 所示,分类数目从 1K 到 1024K 左右。我们观察到当分类数目小于 32K 时,两种模式的迭代次数几乎相同,因为该算法找到了数据 并行(Data-Parallelism,DP)策略。当分类数目超过 64K 后,自动并行模式相比数据并行模式, 在性能上有了较大提升。这是因为当分类数目超过 64K,该算法返回的策略是混合并行(Hybrid Parallelism,HP)(表示模型头部的算子是数据并行的,而 MatMul 算子是模型并行的,如图 3 所示)。 这一过程节省了很大的通信开销,因为模型并行避免了 MatMul 算子中由可学习参数同步引起的大 量 AllReduce。 当分类数目大于 256K 时,由于“内存溢出”(Out of Memory,OOM)失败,数据并行模式甚至不 能运行,而自动并行模式下,ResNet50 训练成功,迭代时间略有增加。

     

    8.2 性能测试

    8.2.1 训练性能

    在昇腾系列芯片的集群上完成了 ResNet50 和 BERT-large 模型的训练,并与 TensorFlow 进行 了对比。TensorFlow 使用 NVIDIA DGX-2(16x V100 32G),我们通过配置不同的 AI 设备数来对比 MindSpore 和 TensorFlow 的训练性能。如图 13 和图 14 所示,随着 AI 设备数的增加,MindSpore 可以获得比 TensorFlow 更大的吞吐量。 如图 15 所示,使用昇腾系列芯片的 MindSpore 在训练 ResNet-50v1.5 和 BERT-large 时都可以获 得超过 93%的加速比。而使用 GPU 的 TensorFlow 在训练 ResNet50 时只能达到 79%的加速比, 在训练 BERT-large 时只能达到 86%的加速比。

     

     

    8.2.2 推理性能

    还使用了不同的轻量级模型在华为 Mate 30 手机上进行了推理实验,如表 2 所示。在 CPU 上 执行,并将推理延迟与 TensorFlow 进行比较。结果表明,MindSpore 比 TensorFlow 具有更短的推 理时延。 表 2 用 MindSpore 和 TensorFlow Lite 在华为 Mate 30 手机进行推理的性能比较。

     

    9 结论及未来工作方向

    在本文中,介绍了新的深度学习框架——MindSpore,重点介绍了 MindSpore 的四个重要组成 部分:ME、GE、MD 和 MA 以及 MindSpore 的几个新特性,即自动并行、自动微分和端边云协同 训练,这使 MindSpore 能够实现易开发、高效执行、全场景覆盖三大目标。此外,MindSpore 还提 供可视化和防御工具,使训练过程对各种对抗性攻击都可见,并且能够抵抗这些攻击。2020 年 3 月 28 日华为发布了 MindSpore 的第一个版本,现在,MindSpore 已经成功与昇腾系列芯片适配,并应 用于华为的各种产品,从智能手机到云。今后,我们计划从几个方面改进现有的 MindSpore 系统。 对于 ME 部分,我们希望考虑拓扑感知的调度,以满足多节点集群中不同的通信需求;对于 GE,我 们将尝试进一步利用昇腾系列芯片来优化计算图;对于 MD,我们将为人工智能工程师提供更灵活 的工具来处理和增强不同类型的数据;对于 MA,我们将尝试在 CV/NLP 领域防御各种对抗性攻击。

    参考文献

     [1] Alex Krizhevsky, Ilya Sutskever, and Geoffrey E Hinton. Imagenet classification with deep convolutional neural networks. In Advances in neural information processing systems, pages 1097–1105, 2012.

    [2] Geoffrey Hinton, Li Deng, Dong Yu, George Dahl, Abdel-rahman Mohamed, Navdeep Jaitly, Andrew Se- nior, Vincent Vanhoucke, Patrick Nguyen, Brian Kings- bury, et al. Deep neural networks for acoustic modeling in speech recognition. IEEE Signal processing maga- zine, 29, 2012.

    [3] Mnih Volodymyr, Kavukcuoglu Koray, Silver David, A Rusu Andrei, and Veness Joel. Human-level control through deep reinforcement learning. Nature, 518(7540):529–533, 2015.

    [4] Yoshua Bengio, Réjean Ducharme, Pascal Vincent, and Christian Jauvin. A neural probabilistic language model. Journal of machine learning research, 3(Feb):1137– 1155, 2003.

    [5] Martín Abadi, Ashish Agarwal, Paul Barham, Eugene Brevdo, Zhifeng Chen, Craig Citro, Greg S Corrado, Andy Davis, Jeffrey Dean, Matthieu Devin, et al. Ten- sorflow: Large-scale machine learning on heterogeneous distributed systems. arXiv preprint arXiv:1603.04467, 2016.

    [6] Adam Paszke, Sam Gross, Soumith Chintala, Gregory Chanan, Edward Yang, Zachary DeVito, Zeming Lin, Alban Desmaison, Luca Antiga, and Adam Lerer. Auto- matic differentiation in pytorch. 2017.

    [7] Tianqi Chen, Mu Li, Yutian Li, Min Lin, Naiyan Wang, Minjie Wang, Tianjun Xiao, Bing Xu, Chiyuan Zhang, and Zheng Zhang. Mxnet: A flexible and efficient ma- chine learning library for heterogeneous distributed sys- tems. arXiv preprint arXiv:1512.01274, 2015.

     [8] Graham Neubig, Chris Dyer, Yoav Goldberg, Austin Matthews, Waleed Ammar, Antonios Anastasopoulos, Miguel Ballesteros, David Chiang, Daniel Clothiaux, Trevor Cohn, et al. Dynet: The dynamic neural network toolkit. arXiv preprint arXiv:1701.03980, 2017.

    [9] Seiya Tokui, Kenta Oono, Shohei Hido, and Justin Clay- ton. Chainer: a next-generation open source frame- work for deep learning. In Proceedings of workshop on machine learning systems (LearningSys) in the twenty- ninth annual conference on neural information process- ing systems (NIPS), volume 5, pages 1–6, 2015.

    [10] Yangqing Jia, Evan Shelhamer, Jeff Donahue, Sergey Karayev, Jonathan Long, Ross Girshick, Sergio Guadar- rama, and Trevor Darrell. Caffe: Convolutional archi- tecture for fast feature embedding. In Proceedings of the 22nd ACM international conference on Multimedia, pages 675–678. ACM, 2014.

    [11] Cynthia Dwork and Jing Lei. Differential privacy and robust statistics. In Proceedings of the forty-first annual ACM symposium on Theory of computing, pages 371– 380, 2009.

    [12] Ran Gilad-Bachrach, Nathan Dowlin, Kim Laine, Kristin Lauter, Michael Naehrig, and John Wernsing. Cryptonets: Applying neural networks to encrypted data with high throughput and accuracy. In International Conference on Machine Learning, pages 201–210, 2016.

    [13] Luca Melis, Congzheng Song, Emiliano De Cristofaro, and Vitaly Shmatikov. Exploiting unintended feature leakage in collaborative learning. In 2019 IEEE Sym- posium on Security and Privacy (SP), pages 691–706. IEEE, 2019.

    [14] Lingchen Zhao, Qian Wang, Qin Zou, Yan Zhang, and Yanjiao Chen. Privacy-preserving collaborative deep learning with unreliable participants. IEEE Transactions on Information Forensics and Security, 15:1486–1500, 2019.

    [15] Cormac Flanagan, Amr Sabry, Bruce F Duba, and Matthias Felleisen. The essence of compiling with con- tinuations. In Proceedings of the ACM SIGPLAN 1993 conference on Programming language design and im- plementation, pages 237–247, 1993.

    [16] Bart van Merrienboer, Olivier Breuleux, Arnaud Berg- eron, and Pascal Lamblin. Automatic differentiation in ml: Where we are and where we should be going. In Advances in neural information processing systems, pages 8757–8767, 2018.

    [17] Yann LeCun et al. Lenet-5, convolutional neural net- works. URL: http://yann. lecun. com/exdb/lenet, 20:5, 2015.

     [18] Jacob Devlin, Ming-Wei Chang, Kenton Lee, and Kristina Toutanova. Bert: Pre-training of deep bidirec- tional transformers for language understanding. arXiv preprint arXiv:1810.04805, 2018. [19] Alec Radford, Jeffrey Wu, Rewon Child, David Luan, Dario Amodei, and Ilya Sutskever. Language models are unsupervised multitask learners. OpenAI Blog, 1(8), 2019.

    [20] Mohammad Shoeybi, Mostofa Patwary, Raul Puri, Patrick LeGresley, Jared Casper, and Bryan Catanzaro. Megatron-lm: Training multi-billion parameter language models using gpu model parallelism. arXiv preprint arXiv:1909.08053, 2019.

    [21] Noam Shazeer, Youlong Cheng, Niki Parmar, Dustin Tran, Ashish Vaswani, Penporn Koanantakool, Peter Hawkins, HyoukJoong Lee, Mingsheng Hong, Cliff Young, Ryan Sepassi, and Blake Hechtman. Mesh- tensorflow: Deep learning for supercomputers. In Advances in Neural Information Processing Systems (NeurIPS), pages 10414–10423. Curran Associates, Inc., 2018.

    [22] Zhihao Jia, Sina Lin, Charles R. Qi, and Alex Aiken. Ex- ploring hidden dimensions in accelerating convolutional neural networks. In Proceedings of the 35th Interna- tional Conference on Machine Learning (ICML), pages 2274–2283. PMLR, 2018.

    [23] Zhihao Jia, Matei Zaharia, and Alex Aiken. Beyond data and model parallelism for deep neural networks. In Pro- ceedings of the 2nd Conference on Machine Learning and Systems (MLSys). ACM, 2019.

    [24] Minjie Wang, Chien-chin Huang, and Jinyang Li. Sup- porting very large models using automatic dataflow graph partitioning. In Proceedings of the Fourteenth EuroSys Conference (EuroSys). ACM, 2019.

    [25] Linghao Song, Jiachen Mao, Youwei Zhuo, Xuehai Qian, Hai Li, and Yiran Chen. Hypar: Towards hybrid par- allelism for deep learning accelerator array. In 2019 IEEE International Symposium on High Performance Computer Architecture (HPCA), pages 56–68. IEEE, 2019.

    [26] Ian J Goodfellow, Jonathon Shlens, and Christian Szegedy. Explaining and harnessing adversarial exam- ples. arXiv preprint arXiv:1412.6572, 2014.

    [27] Naveed Akhtar and Ajmal Mian. Threat of adversarial attacks on deep learning in computer vision: A survey. IEEE Access, 6:14410–14430, 2018.

    [28] Alexey Kurakin, Ian Goodfellow, and Samy Bengio. Ad- versarial examples in the physical world. arXiv preprint arXiv:1607.02533, 2016.

    [29] Nicholas Carlini and David Wagner. Towards evaluating the robustness of neural networks. In 2017 ieee sympo- sium on security and privacy (sp), pages 39–57. IEEE, 2017.

    [30] Matt Fredrikson, Somesh Jha, and Thomas Ristenpart. Model inversion attacks that exploit confidence infor- mation and basic countermeasures. In Proceedings of the 22nd ACM SIGSAC Conference on Computer and Communications Security, pages 1322–1333, 2015.

     [31] Reza Shokri, Marco Stronati, Congzheng Song, and Vi- taly Shmatikov. Membership inference attacks against machine learning models. In 2017 IEEE Symposium on Security and Privacy (SP), pages 3–18. IEEE, 2017. [32] Thomas Elsken, Jan Hendrik Metzen, and Frank Hutter. Neural architecture search: A survey. arXiv preprint arXiv:1808.05377, 2018.

    人工智能芯片与自动驾驶
  • 相关阅读:
    基础 之 数组
    记录某个进程任意的采集时间内,top 10 的cpu和内存值的平均和求和
    8、广度优先搜索
    7、散列表
    计算机网络之从接入网到互联网
    计算机网络
    15、python之导入模块
    14、函数之匿名函数(lambda)
    13、python中的函数(闭包与装饰器)
    6、快速排序
  • 原文地址:https://www.cnblogs.com/wujianming-110117/p/14317296.html
Copyright © 2011-2022 走看看