pytorch源码学习03 nn.Module 提纲挈领
深入理解 PyTorch 的 nn.Module:核心概念与底层逻辑 掌握核心思想,探索底层逻辑,编译通过解析 PyTorch 的源码 nn.Module 来构建深度学习模型。此模块是编译 PyTorch 的基石,封装了一系列函数和操作,源码构成计算图,编译溯源码怎么是源码构建神经网络的首选工具。 nn.Module 初始化(__init__) 在定义自定义模块时,编译__init__ 方法是源码关键。通过调用 super().setattr 方法,编译设置 nn.Module 的源码核心成员变量,如训练状态、编译参数、源码缓存等,编译这决定了模块的源码主要功能。这些设置包括:控制训练/测试状态
初始化参数集合
初始化缓存集合
设置非持久缓存集
注册前向和反向钩子
初始化子模块集合
理解这些设置对于高效初始化模块至关重要,避免了默认属性设置的冗余和潜在的性能影响。 训练与测试模式(train/val) nn.Module 通过 self.training 属性区分训练和测试模式,影响模块在不同状态下的行为。使用 model.train() 和 model.eval() 设置,可使模块在训练或测试时表现不同,如控制 Batch Normalization 和 Dropout 的行为。 梯度管理 requires_grad_ 和 zero_grad 函数管理梯度,用于训练和微调模型。requires_grad_ 控制参数是否参与梯度计算,zero_grad 清理梯度,释放内存。校服源码系统正确设置这些函数是训练模型的关键。 参数转换与转移 通过调用 nn.Module 提供的函数,如 CPU、type、CUDA 等,可以轻松转换模型参数和缓存到不同数据类型和设备上。这些函数通过 self._apply 实现,确保所有模块和子模块的参数和缓存得到统一处理。 属性增删改查 模块属性管理通过 add_module、register_parameter 和 register_buffer 等方法实现。这些方法不仅设置属性,还管理属性的生命周期和可见性。直接设置属性会触发 nn.Module 的 __setattr__ 方法。 常见属性访问 nn.Module 提供了方便的访问器,如 parameters、buffers、children 和 modules,用于遍历模块中的参数、缓存、子模块等。这些访问器通过迭代器简化了对模块属性的访问。 前向过程与钩子 nn.Module 中的前向过程与钩子管理了模块的执行顺序。forward_pre_hooks、forward_hooks 和 backward_hooks 用于在模块的前向和后向计算阶段触发特定操作,实现如内存管理、中间结果保存等高级功能。安装asp源码 模型加载与保存 模型的保存与加载通过 hook 机制实现,确保在不同版本间兼容。使用 state_dict() 和 load_state_dict() 函数实现模型状态的导出和导入,支持模块及其子模块参数的保存与恢复。 通过深入理解 nn.Module 的设计与实现,可以更高效地构建、优化和管理深度学习模型,实现从概念到应用的无缝过渡。是什么意思module?
"Module" 是计算机科学中的一个术语,它用于描述代码中的一种组织形式。一个 module 是一个独立的源代码文件,其中包含一组相关函数和变量的定义。这些函数和变量可以在其他代码文件中使用。通过将代码分解成模块,开发者可以更容易地管理复杂的代码库和构建可维护的软件系统。
Module 在不同的编程语言中可能有些微的区别。在 Python 中,module 也是一个 .py 文件,它可以包含类、函数、变量和其他对象的定义。这些对象可以通过 import 语句在其他模块中使用。Python 源代码库中已经包含了大量常用的 module,而且开发者也可以自行编写和使用自己的 module。
Module 还可以用于实现代码的模块化设计。通过将代码分解成独立的netty过滤源码模块,我们可以更容易地进行并行化开发,并且可以在不同的项目中重用这些模块。大量的开源项目也使用了 module 进行模块化设计,例如 Node.js、React 和 Django 等。
PyTorch 源码分析(一):torch.nn.Module
nn.Module是PyTorch中最核心和基础的结构,它是操作符/损失函数的基类,同时也是组成各种网络结构的基类(实际上是由多个module组合而成的一个module)。
在Python侧,2.1回调函数注册,2.2 module类定义中,有以下几个重点函数:
重点函数一:将模型的参数移动到CUDA上,内部会遍历其子module。
重点函数二:将模型的参数移动到CPU上,内部会遍历其子module。
重点函数三:将模型的参数转化为fp或者fp等,内部会遍历其子module。
重点函数四:forward函数调用。
重点函数五:返回该net的所有layer。
在类图中,PyTorch的算子都是module的子类,包括自定义算子和整网定义。
在C++侧,3.1 module.to("cuda")详细分析中,本质是将module的parameter&buffer等tensor移动到CUDA上,最终调用的阿里Tdm源码是tensor.to(cuda)。
3.2 module.load/save逻辑中,PyTorch模型保存分为两种,一种是纯参数,一种是带模型结构(PyTorch中的模型结构,本质上是由module、sub-module构造的一个计算图)。
parameter、buffer是通过key-value的形式来存储和检索的,key为module的.name,value为存储具体数据的tensor。
InputArchive/OutputArchive的write和read逻辑。
通过Module,PyTorch将op/loss/opt等串联起来,类似于一个计算图。基于PyTorch构建的ResNet等模型,是逐个算子进行计算的,tensor在CPU和GPU之间来回流动,而不是整个计算都在GPU上完成(即中间计算结果不出GPU)。实际上,在进行推理时,可以构建一个计算图,让整个计算图的计算都在GPU上完成,不知道是否可行(如果GPU上有一个CPU就可以完成这个操作,不知道tensorrt是否是这样的操作)。
阿里云主机源码编译安装python3常见错误处理
源码编译安装python3时,可能遇到的常见错误及其解决方法如下: 在运行应用时,可能遇到如下异常错误:import _ssl报错,ModuleNotFoundError: No module named '_ssl';从smtplib导入SMTP_SSL报错,ImportError: cannot import name 'SMTP_SSL' from 'smtplib';使用sqlite3数据库报错,django.db.utils.NotSupportedError: deterministic=True requires SQLite 3.8.3 or higher。 上述错误发生的原因通常是系统内置的软件工具版本与python解释器依赖的版本不匹配。例如,openssl1.0.2版本可能是阿里云主机默认安装的版本,而python3.可能要求更高的openssl版本。sqlite3数据库报错信息也明确指出内置的sqlite3版本不符合python3.的版本要求。 在python版本无法降级的情况下,解决这些问题的办法是升级对应工具的版本。但需要注意的是,升级后必须重新编译安装python3,否则问题仍然存在。接下来将详细介绍openssl升级、sqlite3升级、源码编译安装python3的步骤以及重新编译python3所需的清理命令。 具体步骤如下: 升级openssl版本:选择与python3.版本匹配的openssl1.1.1。 升级sqlite3版本:以sqlite3..3版本为例介绍升级步骤。 重新编译清理命令:假设python3源码包解压后存放在Python-3..0目录中,编译安装路径为/usr/local/python3.(路径根据实际情况调整)。重新编译安装清理操作命令如下: 具体源码编译python3.步骤如下:Pytorch源码剖析:nn.Module功能介绍及实现原理
nn.Module作为Pytorch的核心类,是构建模型的基础。它提供了一系列功能,包括记录模型的参数,实现网络的前向传播,加载和保存模型数据,以及进行设备和数据类型转换等。这些功能在模型的训练和应用中起到关键作用。
在训练与评估模式间切换,模块的行为会有所不同,如rrelu、dropout、batchnorm等操作在两种模式下表现不同。可学习的参数,如权重和偏置,需要通过梯度下降进行更新。非学习参数,比如batchnorm的running_mean,是训练过程中的统计结果。_buffers包含的Tensor不作为模型的一部分保存。
模块内部包含一系列钩子(hook)函数,用于在特定的前向传播或反向传播阶段执行自定义操作。子模块列表用于存储模型中的所有子模块。
魔术函数__init__在声明对象时自动调用,优化性能的关键在于使用super().__setattr__而非直接赋值。super调用父类的方法,避免不必要的检查,提高效率。使用register_buffer为模块注册可变的中间结果,例如BatchNorm的running_mean。register_parameter用于注册需要梯度下降更新的参数。
递归应用函数用于对模型进行操作,如参数初始化。可以将模型移动到指定设备,转换数据类型,以及注册钩子函数以实现对网络的扩展和修改。
调用魔术方法__call__执行前向传播。nn.Module未实现forward函数,子类需要提供此方法的具体实现。对于线性层等,forward函数定义了特定的运算流程。从检查点加载参数时,模块自动处理兼容性问题,确保模型结构与参数值的兼容。
模块的__setattr__方法被重写,以区别对待Parameter、Module和Buffer。当尝试设置这些特定类型的属性时,执行注册或更新操作。其他属性的设置遵循标准的Python行为。
模块的save方法用于保存模型参数和状态,确保模型结构和参数值在不同设备间转移时的一致性。改变训练状态(如将模型切换到训练或评估模式)是模块管理过程的重要组成部分。
Linux内核中的Module.symvers文件揭秘
在Linux内核开发过程中,常会遇到编译出错提示缺少"Module.symvers"文件的问题。该文件在内核模块的编译流程中扮演关键角色。在传统的C项目中,函数默认为强符号,可在不同文件间直接调用。但Linux内核编译要求函数在其他文件调用前需通过"EXPORT_SYMBOL"导出。每个导出符号都在各自目录下的"Module.symvers"文件中记录,内核编译时汇总这些符号供模块间调用。反之,若模块需提供符号供其他模块调用,同样生成与之对应的"Module.symvers"文件。
以Linux-5..4内核为例,解释"Module.symvers"文件的作用。编译内核时,执行Makefile中的"modules"目标,触发"scripts/Makefile.modpost"文件。此文件执行后进入"__modpost"规则,执行"scripts/Makefile.modfinal"文件,收集所有模块信息。每个模块路径信息存于"modules.order"文件中。在"scripts/Makefile.modfinal"文件中定义了各模块的编译规则。
Linux内核模块编译流程可概述为以下步骤:
步骤:初始化编译环境
步骤:解析模块依赖关系
步骤:生成模块相关信息
步骤:链接模块,生成最终文件
以"hello.ko"为例,此模块由"hello.o"、"hello.mod.o"链接生成。编译过程中的关键变量包括"KBUILD_EXTMOD",用于指定模块位置,外部编译时由命令行参数"M"指定,内核源码编译时则为空。若模块依赖外部模块,需通过"KBUILD_EXTMOD"指定依赖模块的"Module.symvers"文件,否则会导致编译错误。
总结:Linux内核中,模块编译需依赖生成的"Module.symvers"文件,此文件记录了通过"EXPORT_SYMBOL"导出的全局符号。同样,若外部模块需为内核其他模块提供函数接口,也会生成"Module.symvers"文件。编译时需指定文件位置以调用接口。理解这一原理后,面对编译错误时,应先确保已生成对应"Module.symvers"文件,特别是外部编译的模块,在内核源码外编译时,需先编译内核生成文件,方可避免错误。
2024-11-30 10:17
2024-11-30 09:35
2024-11-30 09:34
2024-11-30 08:14
2024-11-30 08:12