1.PyTorch源码学习系列 - 2. Tensor
2.pytorch 源码解读进阶版 - 当你 import torch 的源码时候,你都干了些什么?(施工中)
3.硬核观察 #758 Rust Linux 驱动程序实现与 C 代码相当的源码性能
4.Python | 加一行注释,让你的源码程序提速10+倍!numba库十分钟上手指南
5.PyTorch 源码分析(三):torch.nn.Norm类算子
6.PyTorch源码学习 - (13)模型的源码保存与加载
PyTorch源码学习系列 - 2. Tensor
本系列文章同步发布于微信公众号小飞怪兽屋及知乎专栏PyTorch源码学习-知乎(zhihu.com),欢迎关注。源码
若问初学者接触PyTorch应从何学起,源码声明事务源码解析答案非神经网络(NN)或自动求导系统(Autograd)莫属,源码而是源码看似平凡却无所不在的张量(Tensor)。正如编程初学者在控制台输出“Hello World”一样,源码Tensor是源码PyTorch的“Hello World”,每个初学者接触PyTorch时,源码都通过torch.tensor函数创建自己的源码Tensor。
编写上述代码时,源码我们已步入PyTorch的源码宏观世界,利用其函数创建Tensor对象。源码然而,Tensor是如何创建、存储、设计的?今天,让我们深入探究Tensor的微观世界。
Tensor是什么?从数学角度看,Tensor本质上是多维向量。在数学里,数称为标量,一维数据称为向量,二维数据称为矩阵,三维及以上数据统称为张量。维度是衡量事物的方式,例如时间是一种维度,销售额相对于时间的后台源码怎么发布关系可视为一维Tensor。Tensor用于表示多维数据,在不同场景下具有不同的物理含义。
如何存储Tensor?在计算机中,程序代码、数据和生成数据都需要加载到内存。存储Tensor的物理媒介是内存(GPU上是显存),内存是一块可供寻址的存储单元。设计Tensor存储方案时,需要先了解其特性,如数组。创建数组时,会向内存申请一块指定大小的连续存储空间,这正是PyTorch中Strided Tensor的存储方式。
PyTorch引入了步伐(Stride)的概念,表示逻辑索引的相对距离。例如,一个二维矩阵的Stride是一个大小为2的一维向量。Stride用于快速计算元素的物理地址,类似于C/C++中的多级指针寻址方式。Tensor支持Python切片操作,因此PyTorch引入视图概念,使所有Tensor视图共享同一内存空间,提高程序运行效率并减少内存空间浪费。
PyTorch将Tensor的物理存储抽象成一个Storage类,与逻辑表示类Tensor解耦,建立Tensor视图和物理存储Storage之间多对一的联系。Storage是声明类,具体实现在实现类StorageImpl中。StorageImp有两个核心成员:Storage和StorageImpl。呼伦贝尔直播源码
PyTorch的Tensor不仅用Storage类管理物理存储,还在Tensor中定义了很多相关元信息,如size、stride和dtype,这些信息都存在TensorImpl类中的sizes_and_strides_和data_type_中。key_set_保存PyTorch对Tensor的layout、device和dtype相关的调度信息。
PyTorch创建了一个TensorBody.h的模板文件,在该文件中创建了一个继承基类TensorBase的类Tensor。TensorBase基类封装了所有与Tensor存储相关的细节。在类Tensor中,PyTorch使用代码自动生成工具将aten/src/ATen/native/native_functions.yaml中声明的函数替换此处的宏${ tensor_method_declarations}
Python中的Tensor继承于基类_TensorBase,该类是用Python C API绑定的一个C++类。THPVariable_initModule函数除了声明一个_TensorBase Python类之外,还通过torch::autograd::initTorchFunctions(module)函数声明Python Tensor相关的函数。
torch.Tensor会调用C++的THPVariable_tensor函数,该函数在文件torch/csrc/autograd/python_torch_functions_manual.cpp中。在经过一系列参数检测之后,在函数结束之前调用了torch::utils::tensor_ctor函数。
torch::utils::tensor_ctor在文件torch/csrc/utils/tensor_new.cpp中,该文件包含了创建Tensor的一些工具函数。在该函数中调用了internal_new_from_data函数创建Tensor。
recursive_store函数的核心在于
Tensor创建后,我们需要通过函数或方法对其进行操作。Tensor的方法主要通过torch::autograd::variable_methods和extra_methods两个对象初始化。Tensor的函数则是通过initTorchFunctions初始化,调用gatherTorchFunctions来初始化函数,主要分为两种函数:内置函数和自定义函数。
pytorch 源码解读进阶版 - 当你 import torch 的暴涨金柱指标源码时候,你都干了些什么?(施工中)
使用PyTorch,无论是训练还是预测,你首先编写的代码通常如下所示:
依据Python代码的编写规则,导入逻辑将去相应的PyTorch site-package目录寻找__init__.py文件,具体路径为:${ python_path}/lib/python3.8/site-packages/torch/__init__.py
本章节聚焦于__init__.py 这个Python文件,从这里开始深入剖析,探究在一行简单的`import torch`命令背后,PyTorch是如何完成关键基础设置的初始化。
重点一:从`from torch._C import *`开始
在__init__.py 中,首先跳过一些系统环境的检查和判断逻辑,核心代码段为`from torch._C import *`,具体位置如下(github.com/pytorch/pytorch...):
这代表了典型的C++共享库初始化过程,遵循CPython代码组织规则,`torch._C`模块对应一个名为PyInit__C的函数。在文件torch/csrc/stub.c中,找到了此函数的相关定义(github.com/pytorch/pytorch...)。
initModule被视为PyTorch初始化过程中的第一层调用栈,深入探讨此函数中的关键内容。
硬核观察 # Rust Linux 驱动程序实现与 C 代码相当的性能
在年Linux Plumbers大会的Rust小型会议上,展示了Linux内核中Rust语言驱动的最新情况。西部数据对Rust NVMe驱动进行了测试,结果表明,尽管该驱动仍处于早期阶段,但其性能与使用C语言编写的驱动相同。会议还提到了补丁系列的精简,以及过去一年的进展。Rust何时能够进入内核主线,会议并未透露具体时间表和进展。
PyTorch成为Linux基金会顶级项目,钓场抽号源码成立PyTorch基金会,成员包括AMD、AWS、谷歌云、Meta、Azure和英伟达等。自年,有超过名开发者在PyTorch基础上创建了个项目,使其成为AI研究的主要平台之一。
思科承认遭受“阎罗王”勒索团伙攻击并泄露数据,但声明业务未受影响。该团伙在暗网上公开泄露**的GB文件,包括源代码和机密材料。思科威胁情报部门证实了文件的真实性,但强调业务未受到不利影响。然而,“阎罗王”勒索组织声称窃取了大量敏感信息。
Python | 加一行注释,让你的程序提速+倍!numba库十分钟上手指南
如果你在使用Python进行高性能计算,Numba提供的加速效果可以比肩原生的C/C++程序,只需要在函数上添加一行@jit的装饰。它支持CPU和GPU,是数据科学家必不可少的编程利器。
之前的文章已经提到计算机只能执行二进制的机器码,C、C++等编译型语言依靠编译器将源代码转化为可执行文件后才能运行,Python、Java等解释型语言使用解释器将源代码翻译后在虚拟机上执行。对于Python,由于解释器的存在,其执行效率比C语言慢几倍甚至几十倍。
解决Python执行效率低的问题,一种解决办法是使用C/C++语言重写Python函数,但是这要求程序员对C/C++语言熟悉,且调试速度慢,不适合绝大多数Python程序员。另外一种非常方便快捷的解决办法就是使用Just-In-Time(JIT)技术,本文将解释JIT技术的原理,并提供几个案例,让你十分钟内学会JIT技术。
Python解释器工作原理,Python是一门解释语言,Python为我们提供了基于硬件和操作系统的一个虚拟机,并使用解释器将源代码转化为字节码。字节码在虚拟机上执行,得到结果。
使用Python example.py执行源代码时,Python解释器会在后台启动字节码编译器,将源代码转换为字节码。字节码是一种只能运行在虚拟机上的文件,Python生成的字节码默认后缀为.pyc,Python生成.pyc后一般放在内存中继续使用,并不是每次都将.pyc文件保存到磁盘上。pyc字节码通过Python虚拟机与硬件交互。虚拟机的出现导致程序和硬件之间增加了中间层,运行效率大打折扣。
Just-In-Time(JIT)技术为解释语言提供了一种优化,它能克服上述效率问题,极大提升代码执行速度,同时保留Python语言的易用性。使用JIT技术时,JIT编译器将Python源代码编译成机器直接可以执行的机器语言,并可以直接在CPU等硬件上运行。这样就跳过了原来的虚拟机,执行速度几乎与用C语言编程速度并无二致。
Numba是一个针对Python的开源JIT编译器,可以对原生代码进行CPU和GPU加速。使用conda或pip安装Numba。只需要在原来的函数上添加一行@jit,即可将一个函数编译成机器码,执行速度提升倍,且随着数据和计算量的增大,numba的性能提升可能会更大。
Numba的使用场景,只需在函数上加装饰器即可加速程序,但有缺点,只支持Python原生函数和部分NumPy函数,不支持pandas、scikit-learn、tensorflow、pytorch等高级封装。Numba在nopython模式下强制使用加速方式,不进入object模式,保证加速效果。对于计算密集部分,使用nopython优化,其余部分使用Python原生代码,兼顾加速与编译时间。
编译开销较小,Numba的懒编译技术仅在运行时首次发现@jit才编译代码块,第二次使用时使用缓存,运行时间大大缩短。Eager Compilation优化方式告知Numba输入输出类型,加快编译速度。
Numba性能评测显示,结合NumPy,可得到接近C语言的速度。Numba功能多样,包括@vectorize装饰器使函数向量化,以及使用GPU加速等。
Numba原理基于LLVM和NVVM技术,可将解释语言直接翻译成机器码。无论在金融量化分析、计算机视觉或矩阵和张量处理中,Numba提供比肩C/C++程序的加速效果,是数据科学家的编程利器。
PyTorch 源码分析(三):torch.nn.Norm类算子
PyTorch源码详解(三):torch.nn.Norm类算子深入解析
Norm类算子在PyTorch中扮演着关键角色,它们包括BN(BatchNorm)、LayerNorm和InstanceNorm。1. BN/LayerNorm/InstanceNorm详解
BatchNorm(BN)的核心功能是对每个通道(C通道)的数据进行标准化,确保数据在每个批次后保持一致的尺度。它通过学习得到的gamma和beta参数进行缩放和平移,保持输入和输出形状一致,同时让数据分布更加稳定。 gamma和beta作为动态调整权重的参数,它们在BN的学习过程中起到至关重要的作用。2. Norm算子源码分析
继承关系:Norm类在PyTorch中具有清晰的继承结构,子类如BatchNorm和InstanceNorm分别继承了其特有的功能。
BN与InstanceNorm实现:在Python代码中,BatchNorm和InstanceNorm的实例化和计算逻辑都包含对输入数据的2D转换,即将其分割为M*N的矩阵。
计算过程:在计算过程中,首先计算每个通道的均值和方差,这是这些标准化方法的基础步骤。
C++侧的源码洞察
C++实现中,对于BatchNorm和LayerNorm,代码着重于处理数据的标准化操作,同时确保线程安全,通过高效的数据视图和线程视图处理来提高性能。PyTorch源码学习 - ()模型的保存与加载
在PyTorch源码中,模型的保存与加载是通过`torch.save`和`torch.load`两个核心函数实现的。`torch.save`负责将一个Python对象持久化到磁盘文件,而`torch.load`则用于从磁盘文件中恢复对象。
在具体的实现中,`torch.save`会使用一系列辅助函数如`torch._opener`,`torch._open_zipfile_writer`,`torch._open_zipfile_writer_file`,`torch._open_zipfile_writer_buffer`等来操作文件和流。根据文件或内存缓冲区创建流容器,进行对象的保存。`torch._save`则进一步封装了文件的打开和写入过程,`torch._open_file_like`和`torch._open_file`用于管理文件句柄,`torch._open_buffer_writer`和`torch._open_buffer_reader`则封装了二进制流的读写。
对于模型加载,`torch.load`函数通过`torch._open_zipfile_reader`和`torch._weights_only_unpickler`实现。`torch._weights_only_unpickler`是定制的反序列化器,限制了处理的数据类型,确保安全加载模型权重。`torch._get_restore_location`和`torch.default_restore_location`则用于获取和设置恢复位置,以支持在多设备或分布式环境下的模型加载。
实现中,Python和C++的结合是关键,PyTorch使用`PyBind`实现C++和Python接口的绑定。`torch/_C/ __init__.pyi`用于定义Python中类型信息的模板,`torch/csrc/jit/python/init.cpp`则用于实现JIT(Just-In-Time)编译系统,将C++类对象绑定到Python环境,实现高效的动态编译。
在PyTorch中,Python主要负责管理C++对象,核心工作包括管理C++对象的生命周期、调用C++方法,以及处理Python层面的逻辑和接口定义。通过这样的结合,PyTorch实现了高性能和易用性的统一,为深度学习模型的开发和应用提供了强大支持。
整体来看,PyTorch的模型保存与加载机制通过精细的文件操作和对象管理,以及Python与C++的高效结合,确保了模型的高效持久化与灵活加载,为深度学习模型的开发与部署提供了坚实的底层支持。